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
26af05ea
Commit
26af05ea
authored
Sep 11, 2002
by
Jens Axboe
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update of the legcay ide controller drivers. mainly the IN_BYTE -> inb()
and preparation for truly modular low level drivers.
parent
0d1e8f1f
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
876 additions
and
325 deletions
+876
-325
drivers/ide/legacy/ali14xx.c
drivers/ide/legacy/ali14xx.c
+102
-21
drivers/ide/legacy/buddha.c
drivers/ide/legacy/buddha.c
+11
-3
drivers/ide/legacy/dtc2278.c
drivers/ide/legacy/dtc2278.c
+81
-10
drivers/ide/legacy/falconide.c
drivers/ide/legacy/falconide.c
+3
-1
drivers/ide/legacy/gayle.c
drivers/ide/legacy/gayle.c
+7
-1
drivers/ide/legacy/hd.c
drivers/ide/legacy/hd.c
+0
-7
drivers/ide/legacy/ht6560b.c
drivers/ide/legacy/ht6560b.c
+147
-58
drivers/ide/legacy/ide-cs.c
drivers/ide/legacy/ide-cs.c
+2
-2
drivers/ide/legacy/macide.c
drivers/ide/legacy/macide.c
+15
-9
drivers/ide/legacy/pdc4030.c
drivers/ide/legacy/pdc4030.c
+249
-107
drivers/ide/legacy/q40ide.c
drivers/ide/legacy/q40ide.c
+3
-1
drivers/ide/legacy/qd65xx.c
drivers/ide/legacy/qd65xx.c
+162
-92
drivers/ide/legacy/umc8672.c
drivers/ide/legacy/umc8672.c
+94
-13
No files found.
drivers/ide/legacy/ali14xx.c
View file @
26af05ea
...
...
@@ -39,6 +39,8 @@
#undef REALLY_SLOW_IO
/* most systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
...
...
@@ -52,14 +54,20 @@
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_ALI14XX_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif
/* CONFIG_BLK_DEV_ALI14XX_MODULE */
/* port addresses for auto-detection */
#define ALI_NUM_PORTS 4
static
int
ports
[
ALI_NUM_PORTS
]
__initdata
=
{
0x074
,
0x0f4
,
0x034
,
0x0e4
};
/* register initialization data */
typedef
struct
{
byte
reg
,
data
;
}
RegInitializer
;
typedef
struct
{
u8
reg
,
data
;
}
RegInitializer
;
static
RegInitializer
initData
[]
__initdata
=
{
{
0x01
,
0x0f
},
{
0x02
,
0x00
},
{
0x03
,
0x00
},
{
0x04
,
0x00
},
...
...
@@ -74,7 +82,7 @@ static RegInitializer initData[] __initdata = {
#define ALI_MAX_PIO 4
/* timing parameter registers for each drive */
static
struct
{
byte
reg1
,
reg2
,
reg3
,
reg4
;
}
regTab
[
4
]
=
{
static
struct
{
u8
reg1
,
reg2
,
reg3
,
reg4
;
}
regTab
[
4
]
=
{
{
0x03
,
0x26
,
0x04
,
0x27
},
/* drive 0 */
{
0x05
,
0x28
,
0x06
,
0x29
},
/* drive 1 */
{
0x2b
,
0x30
,
0x2c
,
0x31
},
/* drive 2 */
...
...
@@ -84,24 +92,24 @@ static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = {
static
int
basePort
;
/* base port address */
static
int
regPort
;
/* port for register number */
static
int
dataPort
;
/* port for register data */
static
byte
regOn
;
/* output to base port to access registers */
static
byte
regOff
;
/* output to base port to close registers */
static
u8
regOn
;
/* output to base port to access registers */
static
u8
regOff
;
/* output to base port to close registers */
/*------------------------------------------------------------------------*/
/*
* Read a controller register.
*/
static
inline
byte
inReg
(
byte
reg
)
static
inline
u8
inReg
(
u8
reg
)
{
outb_p
(
reg
,
regPort
);
return
IN_BYTE
(
dataPort
);
return
inb
(
dataPort
);
}
/*
* Write a controller register.
*/
static
void
outReg
(
byte
data
,
byte
reg
)
static
void
outReg
(
u8
data
,
u8
reg
)
{
outb_p
(
reg
,
regPort
);
outb_p
(
data
,
dataPort
);
...
...
@@ -112,11 +120,11 @@ static void outReg (byte data, byte reg)
* This function computes timing parameters
* and sets controller registers accordingly.
*/
static
void
ali14xx_tune_drive
(
ide_drive_t
*
drive
,
byte
pio
)
static
void
ali14xx_tune_drive
(
ide_drive_t
*
drive
,
u8
pio
)
{
int
driveNum
;
int
time1
,
time2
;
byte
param1
,
param2
,
param3
,
param4
;
u8
param1
,
param2
,
param3
,
param4
;
unsigned
long
flags
;
ide_pio_data_t
d
;
int
bus_speed
=
system_bus_clock
();
...
...
@@ -132,7 +140,7 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
param3
+=
8
;
param4
+=
8
;
}
printk
(
"%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d
\n
"
,
printk
(
KERN_DEBUG
"%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d
\n
"
,
drive
->
name
,
pio
,
time1
,
time2
,
param1
,
param2
,
param3
,
param4
);
/* stuff timing parameters into controller registers */
...
...
@@ -153,16 +161,16 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
static
int
__init
findPort
(
void
)
{
int
i
;
byte
t
;
u8
t
;
unsigned
long
flags
;
local_irq_save
(
flags
);
for
(
i
=
0
;
i
<
ALI_NUM_PORTS
;
++
i
)
{
basePort
=
ports
[
i
];
regOff
=
IN_BYTE
(
basePort
);
regOff
=
inb
(
basePort
);
for
(
regOn
=
0x30
;
regOn
<=
0x33
;
++
regOn
)
{
outb_p
(
regOn
,
basePort
);
if
(
IN_BYTE
(
basePort
)
==
regOn
)
{
if
(
inb
(
basePort
)
==
regOn
)
{
regPort
=
basePort
+
4
;
dataPort
=
basePort
+
8
;
t
=
inReg
(
0
)
&
0xf0
;
...
...
@@ -184,7 +192,7 @@ static int __init findPort (void)
*/
static
int
__init
initRegisters
(
void
)
{
RegInitializer
*
p
;
byte
t
;
u8
t
;
unsigned
long
flags
;
local_irq_save
(
flags
);
...
...
@@ -192,21 +200,21 @@ static int __init initRegisters (void) {
for
(
p
=
initData
;
p
->
reg
!=
0
;
++
p
)
outReg
(
p
->
data
,
p
->
reg
);
outb_p
(
0x01
,
regPort
);
t
=
IN_BYTE
(
regPort
)
&
0x01
;
t
=
inb
(
regPort
)
&
0x01
;
outb_p
(
regOff
,
basePort
);
local_irq_restore
(
flags
);
return
t
;
}
void
__init
init
_ali14xx
(
void
)
int
__init
probe
_ali14xx
(
void
)
{
/* auto-detect IDE controller port */
if
(
!
findPort
())
{
printk
(
"
\n
ali14xx: not found
"
);
return
;
printk
(
KERN_ERR
"ali14xx: not found.
\n
"
);
return
1
;
}
printk
(
"
\n
ali14xx: base= 0x%03x, regOn = 0x%02x
"
,
basePort
,
regOn
);
printk
(
KERN_DEBUG
"ali14xx: base= 0x%03x, regOn = 0x%02x.
\n
"
,
basePort
,
regOn
);
ide_hwifs
[
0
].
chipset
=
ide_ali14xx
;
ide_hwifs
[
1
].
chipset
=
ide_ali14xx
;
ide_hwifs
[
0
].
tuneproc
=
&
ali14xx_tune_drive
;
...
...
@@ -217,7 +225,80 @@ void __init init_ali14xx (void)
/* initialize controller registers */
if
(
!
initRegisters
())
{
printk
(
"
\n
ali14xx: Chip initialization failed"
);
printk
(
KERN_ERR
"ali14xx: Chip initialization failed.
\n
"
);
return
1
;
}
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init
(
&
ide_hwifs
[
0
]);
probe_hwif_init
(
&
ide_hwifs
[
1
]);
#endif
/* HWIF_PROBE_CLASSIC_METHOD */
return
0
;
}
void
__init
ali14xx_release
(
void
)
{
if
(
ide_hwifs
[
0
].
chipset
!=
ide_ali14xx
&&
ide_hwifs
[
1
].
chipset
!=
ide_ali14xx
)
return
;
ide_hwifs
[
0
].
chipset
=
ide_unknown
;
ide_hwifs
[
1
].
chipset
=
ide_unknown
;
ide_hwifs
[
0
].
tuneproc
=
NULL
;
ide_hwifs
[
1
].
tuneproc
=
NULL
;
ide_hwifs
[
0
].
mate
=
NULL
;
ide_hwifs
[
1
].
mate
=
NULL
;
}
#ifndef MODULE
/*
* init_ali14xx:
*
* called by ide.c when parsing command line
*/
void
__init
init_ali14xx
(
void
)
{
/* auto-detect IDE controller port */
if
(
findPort
())
if
(
probe_ali14xx
())
goto
no_detect
;
return
;
no_detect:
printk
(
KERN_ERR
"ali14xx: not found.
\n
"
);
ali14xx_release
();
}
#else
MODULE_AUTHOR
(
"see local file"
);
MODULE_DESCRIPTION
(
"support of ALI 14XX IDE chipsets"
);
MODULE_LICENSE
(
"GPL"
);
int
__init
ali14xx_mod_init
(
void
)
{
/* auto-detect IDE controller port */
if
(
findPort
())
if
(
probe_ali14xx
())
{
ali14xx_release
();
return
-
ENODEV
;
}
if
(
ide_hwifs
[
0
].
chipset
!=
ide_ali14xx
&&
ide_hwifs
[
1
].
chipset
!=
ide_ali14xx
)
{
ali14xx_release
();
return
-
ENODEV
;
}
return
0
;
}
module_init
(
ali14xx_mod_init
);
void
__init
ali14xx_mod_exit
(
void
)
{
ali14xx_release
();
}
module_exit
(
ali14xx_mod_exit
);
#endif
drivers/ide/legacy/buddha.c
View file @
26af05ea
...
...
@@ -168,7 +168,11 @@ void __init buddha_init(void)
continue
;
board
=
z
->
resource
.
start
;
/*
* FIXME: we now have selectable mmio v/s iomio transports.
*/
if
(
type
!=
BOARD_XSURF
)
{
if
(
!
request_mem_region
(
board
+
BUDDHA_BASE1
,
0x800
,
"IDE"
))
continue
;
...
...
@@ -196,12 +200,16 @@ void __init buddha_init(void)
ide_setup_ports
(
&
hw
,
(
ide_ioreg_t
)(
buddha_board
+
buddha_bases
[
i
]),
buddha_offsets
,
0
,
(
ide_ioreg_t
)(
buddha_board
+
buddha_irqports
[
i
]),
buddha_ack_intr
,
IRQ_AMIGA_PORTS
);
buddha_ack_intr
,
// budda_iops,
IRQ_AMIGA_PORTS
);
}
else
{
ide_setup_ports
(
&
hw
,
(
ide_ioreg_t
)(
buddha_board
+
xsurf_bases
[
i
]),
xsurf_offsets
,
0
,
(
ide_ioreg_t
)(
buddha_board
+
xsurf_irqports
[
i
]),
xsurf_ack_intr
,
IRQ_AMIGA_PORTS
);
xsurf_ack_intr
,
// xsurf_iops,
IRQ_AMIGA_PORTS
);
}
index
=
ide_register_hw
(
&
hw
,
NULL
);
...
...
drivers/ide/legacy/dtc2278.c
View file @
26af05ea
...
...
@@ -6,6 +6,8 @@
#undef REALLY_SLOW_IO
/* most systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
...
...
@@ -19,7 +21,13 @@
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_DTC2278_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif
/* CONFIG_BLK_DEV_DTC2278_MODULE */
/*
* Changing this #undef to #define may solve start up problems in some systems.
...
...
@@ -57,20 +65,20 @@ static void sub22 (char b, char c)
int
i
;
for
(
i
=
0
;
i
<
3
;
++
i
)
{
IN_BYTE
(
0x3f6
);
inb
(
0x3f6
);
outb_p
(
b
,
0xb0
);
IN_BYTE
(
0x3f6
);
inb
(
0x3f6
);
outb_p
(
c
,
0xb4
);
IN_BYTE
(
0x3f6
);
if
(
IN_BYTE
(
0xb4
)
==
c
)
{
inb
(
0x3f6
);
if
(
inb
(
0xb4
)
==
c
)
{
outb_p
(
7
,
0xb0
);
IN_BYTE
(
0x3f6
);
inb
(
0x3f6
);
return
;
/* success */
}
}
}
static
void
tune_dtc2278
(
ide_drive_t
*
drive
,
byte
pio
)
static
void
tune_dtc2278
(
ide_drive_t
*
drive
,
u8
pio
)
{
unsigned
long
flags
;
...
...
@@ -95,7 +103,7 @@ static void tune_dtc2278 (ide_drive_t *drive, byte pio)
HWIF
(
drive
)
->
drives
[
!
drive
->
select
.
b
.
unit
].
io_32bit
=
1
;
}
void
__init
init
_dtc2278
(
void
)
void
__init
probe
_dtc2278
(
void
)
{
unsigned
long
flags
;
...
...
@@ -104,9 +112,9 @@ void __init init_dtc2278 (void)
* This enables the second interface
*/
outb_p
(
4
,
0xb0
);
IN_BYTE
(
0x3f6
);
inb
(
0x3f6
);
outb_p
(
0x20
,
0xb4
);
IN_BYTE
(
0x3f6
);
inb
(
0x3f6
);
#ifdef ALWAYS_SET_DTC2278_PIO_MODE
/*
* This enables PIO mode4 (3?) on the first interface
...
...
@@ -129,4 +137,67 @@ void __init init_dtc2278 (void)
ide_hwifs
[
0
].
mate
=
&
ide_hwifs
[
1
];
ide_hwifs
[
1
].
mate
=
&
ide_hwifs
[
0
];
ide_hwifs
[
1
].
channel
=
1
;
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init
(
&
ide_hwifs
[
0
]);
probe_hwif_init
(
&
ide_hwifs
[
1
]);
#endif
/* HWIF_PROBE_CLASSIC_METHOD */
}
void
__init
dtc2278_release
(
void
)
{
if
(
ide_hwifs
[
0
].
chipset
!=
ide_dtc2278
&&
ide_hwifs
[
1
].
chipset
!=
ide_dtc2278
)
return
;
ide_hwifs
[
0
].
serialized
=
0
;
ide_hwifs
[
1
].
serialized
=
0
;
ide_hwifs
[
0
].
chipset
=
ide_unknown
;
ide_hwifs
[
1
].
chipset
=
ide_unknown
;
ide_hwifs
[
0
].
tuneproc
=
NULL
;
ide_hwifs
[
0
].
drives
[
0
].
no_unmask
=
0
;
ide_hwifs
[
0
].
drives
[
1
].
no_unmask
=
0
;
ide_hwifs
[
1
].
drives
[
0
].
no_unmask
=
0
;
ide_hwifs
[
1
].
drives
[
1
].
no_unmask
=
0
;
ide_hwifs
[
0
].
mate
=
NULL
;
ide_hwifs
[
1
].
mate
=
NULL
;
}
#ifndef MODULE
/*
* init_dtc2278:
*
* called by ide.c when parsing command line
*/
void
__init
init_dtc2278
(
void
)
{
probe_dtc2278
();
}
#else
MODULE_AUTHOR
(
"See Local File"
);
MODULE_DESCRIPTION
(
"support of DTC-2278 VLB IDE chipsets"
);
MODULE_LICENSE
(
"GPL"
);
int
__init
dtc2278_mod_init
(
void
)
{
probe_dtc2278
();
if
(
ide_hwifs
[
0
].
chipset
!=
ide_dtc2278
&&
ide_hwifs
[
1
].
chipset
!=
ide_dtc2278
)
{
dtc2278_release
();
return
-
ENODEV
;
}
return
0
;
}
module_init
(
dtc2278_mod_init
);
void
__init
dtc2278_mod_exit
(
void
)
{
dtc2278_release
();
}
module_exit
(
dtc2278_mod_exit
);
#endif
drivers/ide/legacy/falconide.c
View file @
26af05ea
...
...
@@ -59,7 +59,9 @@ void __init falconide_init(void)
int
index
;
ide_setup_ports
(
&
hw
,
(
ide_ioreg_t
)
ATA_HD_BASE
,
falconide_offsets
,
0
,
0
,
NULL
,
IRQ_MFP_IDE
);
0
,
0
,
NULL
,
// falconide_iops,
IRQ_MFP_IDE
);
index
=
ide_register_hw
(
&
hw
,
NULL
);
if
(
index
!=
-
1
)
...
...
drivers/ide/legacy/gayle.c
View file @
26af05ea
...
...
@@ -137,6 +137,10 @@ void __init gayle_init(void)
irqport
=
(
ide_ioreg_t
)
ZTWO_VADDR
(
GAYLE_IRQ_1200
);
ack_intr
=
gayle_ack_intr_a1200
;
}
/*
* FIXME: we now have selectable modes between mmio v/s iomio
*/
phys_base
+=
i
*
GAYLE_NEXT_PORT
;
res_start
=
((
unsigned
long
)
phys_base
)
&
~
(
GAYLE_NEXT_PORT
-
1
);
...
...
@@ -149,7 +153,9 @@ void __init gayle_init(void)
ctrlport
=
GAYLE_HAS_CONTROL_REG
?
(
base
+
GAYLE_CONTROL
)
:
0
;
ide_setup_ports
(
&
hw
,
base
,
gayle_offsets
,
ctrlport
,
irqport
,
ack_intr
,
IRQ_AMIGA_PORTS
);
ctrlport
,
irqport
,
ack_intr
,
// gaule_iops,
IRQ_AMIGA_PORTS
);
index
=
ide_register_hw
(
&
hw
,
NULL
);
if
(
index
!=
-
1
)
{
...
...
drivers/ide/legacy/hd.c
View file @
26af05ea
...
...
@@ -50,13 +50,6 @@
#define DEVICE_NR(device) (minor(device)>>6)
#include <linux/blk.h>
/* ATA commands we use.
*/
#define WIN_SPECIFY 0x91
/* set drive geometry translation */
#define WIN_RESTORE 0x10
#define WIN_READ 0x20
/* 28-Bit */
#define WIN_WRITE 0x30
/* 28-Bit */
#define HD_IRQ 14
/* the standard disk interrupt */
#ifdef __arm__
...
...
drivers/ide/legacy/ht6560b.c
View file @
26af05ea
...
...
@@ -38,6 +38,8 @@
#undef REALLY_SLOW_IO
/* most systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
...
...
@@ -51,7 +53,13 @@
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_HT6560B_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif
/* CONFIG_BLK_DEV_HT6560B_MODULE */
/* #define DEBUG */
/* remove comments for DEBUG messages */
...
...
@@ -68,7 +76,7 @@
* bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?)
*/
#define HT_CONFIG_PORT 0x3e6
#define HT_CONFIG(drivea) (
byte
)(((drivea)->drive_data & 0xff00) >> 8)
#define HT_CONFIG(drivea) (
u8
)(((drivea)->drive_data & 0xff00) >> 8)
/*
* FIFO + PREFETCH (both a/b-model)
*/
...
...
@@ -114,7 +122,7 @@
* Active Time for each drive. Smaller value gives higher speed.
* In case of failures you should probably fall back to a higher value.
*/
#define HT_TIMING(drivea) (
byte
)((drivea)->drive_data & 0x00ff)
#define HT_TIMING(drivea) (
u8
)((drivea)->drive_data & 0x00ff)
#define HT_TIMING_DEFAULT 0xff
/*
...
...
@@ -130,9 +138,9 @@
static
void
ht6560b_selectproc
(
ide_drive_t
*
drive
)
{
unsigned
long
flags
;
static
byte
current_select
=
0
;
static
byte
current_timing
=
0
;
byte
select
,
timing
;
static
u8
current_select
=
0
;
static
u8
current_timing
=
0
;
u8
select
,
timing
;
local_irq_save
(
flags
);
...
...
@@ -144,16 +152,16 @@ static void ht6560b_selectproc (ide_drive_t *drive)
current_timing
=
timing
;
if
(
drive
->
media
!=
ide_disk
||
!
drive
->
present
)
select
|=
HT_PREFETCH_MODE
;
(
void
)
IN_BYTE
(
HT_CONFIG_PORT
);
(
void
)
IN_BYTE
(
HT_CONFIG_PORT
);
(
void
)
IN_BYTE
(
HT_CONFIG_PORT
);
(
void
)
IN_BYTE
(
HT_CONFIG_PORT
);
OUT_BYTE
(
select
,
HT_CONFIG_PORT
);
(
void
)
HWIF
(
drive
)
->
INB
(
HT_CONFIG_PORT
);
(
void
)
HWIF
(
drive
)
->
INB
(
HT_CONFIG_PORT
);
(
void
)
HWIF
(
drive
)
->
INB
(
HT_CONFIG_PORT
);
(
void
)
HWIF
(
drive
)
->
INB
(
HT_CONFIG_PORT
);
HWIF
(
drive
)
->
OUTB
(
select
,
HT_CONFIG_PORT
);
/*
* Set timing for this drive:
*/
OUT_BYTE
(
timing
,
IDE_SELECT_REG
);
(
void
)
IN_BYTE
(
IDE_STATUS_REG
);
HWIF
(
drive
)
->
OUTB
(
timing
,
IDE_SELECT_REG
);
(
void
)
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
);
#ifdef DEBUG
printk
(
"ht6560b: %s: select=%#x timing=%#x
\n
"
,
drive
->
name
,
select
,
timing
);
...
...
@@ -167,31 +175,31 @@ static void ht6560b_selectproc (ide_drive_t *drive)
*/
static
int
__init
try_to_init_ht6560b
(
void
)
{
byte
orig_value
;
u8
orig_value
;
int
i
;
/* Autodetect ht6560b */
if
((
orig_value
=
IN_BYTE
(
HT_CONFIG_PORT
))
==
0xff
)
if
((
orig_value
=
inb
(
HT_CONFIG_PORT
))
==
0xff
)
return
0
;
for
(
i
=
3
;
i
>
0
;
i
--
)
{
OUT_BYTE
(
0x00
,
HT_CONFIG_PORT
);
if
(
!
(
(
~
IN_BYTE
(
HT_CONFIG_PORT
))
&
0x3f
))
{
OUT_BYTE
(
orig_value
,
HT_CONFIG_PORT
);
outb
(
0x00
,
HT_CONFIG_PORT
);
if
(
!
(
(
~
inb
(
HT_CONFIG_PORT
))
&
0x3f
))
{
outb
(
orig_value
,
HT_CONFIG_PORT
);
return
0
;
}
}
OUT_BYTE
(
0x00
,
HT_CONFIG_PORT
);
if
((
~
IN_BYTE
(
HT_CONFIG_PORT
))
&
0x3f
)
{
OUT_BYTE
(
orig_value
,
HT_CONFIG_PORT
);
outb
(
0x00
,
HT_CONFIG_PORT
);
if
((
~
inb
(
HT_CONFIG_PORT
))
&
0x3f
)
{
outb
(
orig_value
,
HT_CONFIG_PORT
);
return
0
;
}
/*
* Ht6560b autodetected
*/
OUT_BYTE
(
HT_CONFIG_DEFAULT
,
HT_CONFIG_PORT
);
OUT_BYTE
(
HT_TIMING_DEFAULT
,
0x1f6
);
/* IDE_SELECT_REG */
(
void
)
IN_BYTE
(
0x1f7
);
/* IDE_STATUS_REG */
outb
(
HT_CONFIG_DEFAULT
,
HT_CONFIG_PORT
);
outb
(
HT_TIMING_DEFAULT
,
0x1f6
);
/* IDE_SELECT_REG */
(
void
)
inb
(
0x1f7
);
/* IDE_STATUS_REG */
printk
(
"
\n
ht6560b "
HT6560B_VERSION
": chipset detected and initialized"
...
...
@@ -202,7 +210,7 @@ static int __init try_to_init_ht6560b(void)
return
1
;
}
static
byte
ht_pio2timings
(
ide_drive_t
*
drive
,
byte
pio
)
static
u8
ht_pio2timings
(
ide_drive_t
*
drive
,
u8
pio
)
{
int
active_time
,
recovery_time
;
int
active_cycles
,
recovery_cycles
;
...
...
@@ -238,7 +246,7 @@ static byte ht_pio2timings(ide_drive_t *drive, byte pio)
printk
(
"ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)
\n
"
,
drive
->
name
,
pio
,
recovery_cycles
,
recovery_time
,
active_cycles
,
active_time
);
#endif
return
(
byte
)((
recovery_cycles
<<
4
)
|
active_cycles
);
return
(
u8
)((
recovery_cycles
<<
4
)
|
active_cycles
);
}
else
{
#ifdef DEBUG
...
...
@@ -252,7 +260,7 @@ static byte ht_pio2timings(ide_drive_t *drive, byte pio)
/*
* Enable/Disable so called prefetch mode
*/
static
void
ht_set_prefetch
(
ide_drive_t
*
drive
,
byte
state
)
static
void
ht_set_prefetch
(
ide_drive_t
*
drive
,
u8
state
)
{
unsigned
long
flags
;
int
t
=
HT_PREFETCH_MODE
<<
8
;
...
...
@@ -278,10 +286,10 @@ static void ht_set_prefetch(ide_drive_t *drive, byte state)
#endif
}
static
void
tune_ht6560b
(
ide_drive_t
*
drive
,
byte
pio
)
static
void
tune_ht6560b
(
ide_drive_t
*
drive
,
u8
pio
)
{
unsigned
long
flags
;
byte
timing
;
u8
timing
;
switch
(
pio
)
{
case
8
:
/* set prefetch off */
...
...
@@ -304,38 +312,119 @@ static void tune_ht6560b (ide_drive_t *drive, byte pio)
#endif
}
void
__init
init
_ht6560b
(
void
)
void
__init
probe
_ht6560b
(
void
)
{
int
t
;
if
(
check_region
(
HT_CONFIG_PORT
,
1
))
{
printk
(
KERN_ERR
"ht6560b: PORT %#x ALREADY IN USE
\n
"
,
HT_CONFIG_PORT
);
}
else
{
if
(
try_to_init_ht6560b
())
{
request_region
(
HT_CONFIG_PORT
,
1
,
ide_hwifs
[
0
].
name
);
ide_hwifs
[
0
].
chipset
=
ide_ht6560b
;
ide_hwifs
[
1
].
chipset
=
ide_ht6560b
;
ide_hwifs
[
0
].
selectproc
=
&
ht6560b_selectproc
;
ide_hwifs
[
1
].
selectproc
=
&
ht6560b_selectproc
;
ide_hwifs
[
0
].
tuneproc
=
&
tune_ht6560b
;
ide_hwifs
[
1
].
tuneproc
=
&
tune_ht6560b
;
ide_hwifs
[
0
].
serialized
=
1
;
/* is this needed? */
ide_hwifs
[
1
].
serialized
=
1
;
/* is this needed? */
ide_hwifs
[
0
].
mate
=
&
ide_hwifs
[
1
];
ide_hwifs
[
1
].
mate
=
&
ide_hwifs
[
0
];
ide_hwifs
[
1
].
channel
=
1
;
request_region
(
HT_CONFIG_PORT
,
1
,
ide_hwifs
[
0
].
name
);
ide_hwifs
[
0
].
chipset
=
ide_ht6560b
;
ide_hwifs
[
1
].
chipset
=
ide_ht6560b
;
ide_hwifs
[
0
].
selectproc
=
&
ht6560b_selectproc
;
ide_hwifs
[
1
].
selectproc
=
&
ht6560b_selectproc
;
ide_hwifs
[
0
].
tuneproc
=
&
tune_ht6560b
;
ide_hwifs
[
1
].
tuneproc
=
&
tune_ht6560b
;
ide_hwifs
[
0
].
serialized
=
1
;
/* is this needed? */
ide_hwifs
[
1
].
serialized
=
1
;
/* is this needed? */
ide_hwifs
[
0
].
mate
=
&
ide_hwifs
[
1
];
ide_hwifs
[
1
].
mate
=
&
ide_hwifs
[
0
];
ide_hwifs
[
1
].
channel
=
1
;
/*
* Setting default configurations for drives
*/
t
=
(
HT_CONFIG_DEFAULT
<<
8
);
t
|=
HT_TIMING_DEFAULT
;
ide_hwifs
[
0
].
drives
[
0
].
drive_data
=
t
;
ide_hwifs
[
0
].
drives
[
1
].
drive_data
=
t
;
t
|=
(
HT_SECONDARY_IF
<<
8
);
ide_hwifs
[
1
].
drives
[
0
].
drive_data
=
t
;
ide_hwifs
[
1
].
drives
[
1
].
drive_data
=
t
;
}
else
printk
(
KERN_ERR
"ht6560b: not found
\n
"
);
/*
* Setting default configurations for drives
*/
t
=
(
HT_CONFIG_DEFAULT
<<
8
);
t
|=
HT_TIMING_DEFAULT
;
ide_hwifs
[
0
].
drives
[
0
].
drive_data
=
t
;
ide_hwifs
[
0
].
drives
[
1
].
drive_data
=
t
;
t
|=
(
HT_SECONDARY_IF
<<
8
);
ide_hwifs
[
1
].
drives
[
0
].
drive_data
=
t
;
ide_hwifs
[
1
].
drives
[
1
].
drive_data
=
t
;
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init
(
&
ide_hwifs
[
0
]);
probe_hwif_init
(
&
ide_hwifs
[
1
]);
#endif
/* HWIF_PROBE_CLASSIC_METHOD */
}
void
__init
ht6560b_release
(
void
)
{
if
(
ide_hwifs
[
0
].
chipset
!=
ide_ht6560b
&&
ide_hwifs
[
1
].
chipset
!=
ide_ht6560b
)
return
;
ide_hwifs
[
0
].
chipset
=
ide_unknown
;
ide_hwifs
[
1
].
chipset
=
ide_unknown
;
ide_hwifs
[
0
].
tuneproc
=
NULL
;
ide_hwifs
[
1
].
tuneproc
=
NULL
;
ide_hwifs
[
0
].
selectproc
=
NULL
;
ide_hwifs
[
1
].
selectproc
=
NULL
;
ide_hwifs
[
0
].
serialized
=
0
;
ide_hwifs
[
1
].
serialized
=
0
;
ide_hwifs
[
0
].
mate
=
NULL
;
ide_hwifs
[
1
].
mate
=
NULL
;
ide_hwifs
[
0
].
drives
[
0
].
drive_data
=
0
;
ide_hwifs
[
0
].
drives
[
1
].
drive_data
=
0
;
ide_hwifs
[
1
].
drives
[
0
].
drive_data
=
0
;
ide_hwifs
[
1
].
drives
[
1
].
drive_data
=
0
;
release_region
(
HT_CONFIG_PORT
,
1
);
}
#ifndef MODULE
/*
* init_ht6560b:
*
* called by ide.c when parsing command line
*/
void
__init
init_ht6560b
(
void
)
{
if
(
check_region
(
HT_CONFIG_PORT
,
1
))
{
printk
(
KERN_NOTICE
"%s: HT_CONFIG_PORT not found
\n
"
,
__FUNCTION__
);
return
;
}
if
(
!
try_to_init_ht6560b
())
{
printk
(
KERN_NOTICE
"%s: HBA not found
\n
"
,
__FUNCTION__
);
return
;
}
probe_ht6560b
();
}
#else
MODULE_AUTHOR
(
"See Local File"
);
MODULE_DESCRIPTION
(
"HT-6560B EIDE-controller support"
);
MODULE_LICENSE
(
"GPL"
);
int
__init
ht6560b_mod_init
(
void
)
{
if
(
check_region
(
HT_CONFIG_PORT
,
1
))
{
printk
(
KERN_NOTICE
"%s: HT_CONFIG_PORT not found
\n
"
,
__FUNCTION__
);
return
-
ENODEV
;
}
if
(
!
try_to_init_ht6560b
())
{
printk
(
KERN_NOTICE
"%s: HBA not found
\n
"
,
__FUNCTION__
);
return
-
ENODEV
;
}
probe_ht6560b
();
if
(
ide_hwifs
[
0
].
chipset
!=
ide_ht6560b
&&
ide_hwifs
[
1
].
chipset
!=
ide_ht6560b
)
{
ht6560b_release
();
return
-
ENODEV
;
}
return
0
;
}
module_init
(
ht6560b_mod_init
);
void
__init
ht6560b_mod_exit
(
void
)
{
ht6560b_release
();
}
module_exit
(
ht6560b_mod_exit
);
#endif
drivers/ide/legacy/ide-cs.c
View file @
26af05ea
...
...
@@ -340,12 +340,12 @@ void ide_config(dev_link_t *link)
/* retry registration in case device is still spinning up */
for
(
i
=
0
;
i
<
10
;
i
++
)
{
if
(
ctl_base
)
OUT_BYTE
(
0x02
,
ctl_base
);
/* Set nIEN = disable device interrupts */
outb
(
0x02
,
ctl_base
);
/* Set nIEN = disable device interrupts */
hd
=
idecs_register
(
io_base
,
ctl_base
,
link
->
irq
.
AssignedIRQ
);
if
(
hd
>=
0
)
break
;
if
(
link
->
io
.
NumPorts1
==
0x20
)
{
if
(
ctl_base
)
OUT_BYTE
(
0x02
,
ctl_base
+
0x10
);
outb
(
0x02
,
ctl_base
+
0x10
);
hd
=
idecs_register
(
io_base
+
0x10
,
ctl_base
+
0x10
,
link
->
irq
.
AssignedIRQ
);
if
(
hd
>=
0
)
{
...
...
drivers/ide/legacy/macide.c
View file @
26af05ea
...
...
@@ -83,7 +83,7 @@ static void macide_mediabay_interrupt(int irq, void *dev_id, struct pt_regs *reg
{
int
state
=
baboon
->
mb_status
&
0x04
;
printk
(
"macide: media bay %s detected
\n
"
,
state
?
"removal"
:
"insertion"
);
printk
(
KERN_INFO
"macide: media bay %s detected
\n
"
,
state
?
"removal"
:
"insertion"
);
}
#endif
...
...
@@ -99,24 +99,30 @@ void macide_init(void)
switch
(
macintosh_config
->
ide_type
)
{
case
MAC_IDE_QUADRA
:
ide_setup_ports
(
&
hw
,
(
ide_ioreg_t
)
IDE_BASE
,
macide_offsets
,
0
,
0
,
macide_ack_intr
,
IRQ_NUBUS_F
);
0
,
0
,
macide_ack_intr
,
// quadra_ide_iops,
IRQ_NUBUS_F
);
index
=
ide_register_hw
(
&
hw
,
NULL
);
break
;
case
MAC_IDE_PB
:
ide_setup_ports
(
&
hw
,
(
ide_ioreg_t
)
IDE_BASE
,
macide_offsets
,
0
,
0
,
macide_ack_intr
,
IRQ_NUBUS_C
);
0
,
0
,
macide_ack_intr
,
// macide_pb_iops,
IRQ_NUBUS_C
);
index
=
ide_register_hw
(
&
hw
,
NULL
);
break
;
case
MAC_IDE_BABOON
:
ide_setup_ports
(
&
hw
,
(
ide_ioreg_t
)
BABOON_BASE
,
macide_offsets
,
0
,
0
,
NULL
,
IRQ_BABOON_1
);
0
,
0
,
NULL
,
// macide_baboon_iops,
IRQ_BABOON_1
);
index
=
ide_register_hw
(
&
hw
,
NULL
);
if
(
index
==
-
1
)
break
;
if
(
macintosh_config
->
ident
==
MAC_MODEL_PB190
)
{
/* Fix breakage in ide-disk.c: drive capacity */
/* is not initialized for drives without a */
/* hardware ID, and we c
na
't get that without */
/* hardware ID, and we c
an
't get that without */
/* probing the drive which freezes a 190. */
ide_drive_t
*
drive
=
&
ide_hwifs
[
index
].
drives
[
0
];
...
...
@@ -136,12 +142,12 @@ void macide_init(void)
if
(
index
!=
-
1
)
{
if
(
macintosh_config
->
ide_type
==
MAC_IDE_QUADRA
)
printk
(
"ide%d: Macintosh Quadra IDE interface
\n
"
,
index
);
printk
(
KERN_INFO
"ide%d: Macintosh Quadra IDE interface
\n
"
,
index
);
else
if
(
macintosh_config
->
ide_type
==
MAC_IDE_PB
)
printk
(
"ide%d: Macintosh Powerbook IDE interface
\n
"
,
index
);
printk
(
KERN_INFO
"ide%d: Macintosh Powerbook IDE interface
\n
"
,
index
);
else
if
(
macintosh_config
->
ide_type
==
MAC_IDE_BABOON
)
printk
(
"ide%d: Macintosh Powerbook Baboon IDE interface
\n
"
,
index
);
printk
(
KERN_INFO
"ide%d: Macintosh Powerbook Baboon IDE interface
\n
"
,
index
);
else
printk
(
"ide%d: Unknown Macintosh IDE interface
\n
"
,
index
);
printk
(
KERN_INFO
"ide%d: Unknown Macintosh IDE interface
\n
"
,
index
);
}
}
drivers/ide/legacy/pdc4030.c
View file @
26af05ea
/* -*- linux-c -*-
* linux/drivers/ide/pdc4030.c Version 0.90 May 27, 1999
*
* Copyright (C) 1995-
1999
Linus Torvalds & authors (see below)
* Copyright (C) 1995-
2002
Linus Torvalds & authors (see below)
*/
/*
* Principal Author/Maintainer:
peterd@pnd-pc.demon.co.uk
* Principal Author/Maintainer:
Peter Denison <promise@pnd-pc.demon.co.uk>
*
* This file provides support for the second port and cache of Promise
* IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2.
...
...
@@ -66,13 +66,18 @@
* some technical information which has shed a glimmer of light on some of the
* problems I was having, especially with writes.
*
* There are still problems with the robustness and efficiency of this driver
* because I still don't understand what the card is doing with interrupts.
* There are still potential problems with the robustness and efficiency of
* this driver because I still don't understand what the card is doing with
* interrupts, however, it has been stable for a while with no reports of ill
* effects.
*/
#define DEBUG_READ
#define DEBUG_WRITE
#define __PROMISE_4030
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
...
...
@@ -98,7 +103,7 @@ static void promise_selectproc (ide_drive_t *drive)
unsigned
int
number
;
number
=
(
HWIF
(
drive
)
->
channel
<<
1
)
+
drive
->
select
.
b
.
unit
;
OUT_BYTE
(
number
,
IDE_FEATURE_REG
);
HWIF
(
drive
)
->
OUTB
(
number
,
IDE_FEATURE_REG
);
}
/*
...
...
@@ -106,26 +111,24 @@ static void promise_selectproc (ide_drive_t *drive)
* by command F0. They all have the same success/failure notification -
* 'P' (=0x50) on success, 'p' (=0x70) on failure.
*/
int
pdc4030_cmd
(
ide_drive_t
*
drive
,
byte
cmd
)
int
pdc4030_cmd
(
ide_drive_t
*
drive
,
u8
cmd
)
{
u
nsigned
long
timeout
,
timer
;
byte
status_val
;
u
32
timeout
;
u8
status_val
;
promise_selectproc
(
drive
);
/* redundant? */
OUT_BYTE
(
0xF3
,
IDE_SECTOR_REG
);
OUT_BYTE
(
cmd
,
IDE_SELECT_REG
);
OUT_BYTE
(
PROMISE_EXTENDED_COMMAND
,
IDE_COMMAND_REG
);
HWIF
(
drive
)
->
OUTB
(
0xF3
,
IDE_SECTOR_REG
);
HWIF
(
drive
)
->
OUTB
(
cmd
,
IDE_SELECT_REG
);
HWIF
(
drive
)
->
OUTB
(
PROMISE_EXTENDED_COMMAND
,
IDE_COMMAND_REG
);
timeout
=
HZ
*
10
;
timeout
+=
jiffies
;
do
{
if
(
time_after
(
jiffies
,
timeout
))
{
return
2
;
/* device timed out */
}
/* This is out of delay_10ms() */
/* Delays at least 10ms to give interface a chance */
timer
=
jiffies
+
(
HZ
+
99
)
/
100
+
1
;
while
(
time_after
(
timer
,
jiffies
));
status_val
=
IN_BYTE
(
IDE_SECTOR_REG
);
mdelay
(
10
);
status_val
=
HWIF
(
drive
)
->
INB
(
IDE_SECTOR_REG
);
}
while
(
status_val
!=
0x50
&&
status_val
!=
0x70
);
if
(
status_val
==
0x50
)
...
...
@@ -142,18 +145,13 @@ int pdc4030_identify(ide_drive_t *drive)
return
pdc4030_cmd
(
drive
,
PROMISE_IDENTIFY
);
}
int
enable_promise_support
=
0
;
void
__init
init_pdc4030
(
void
)
{
enable_promise_support
=
1
;
}
int
enable_promise_support
;
/*
* setup_pdc4030()
* Completes the setup of a Promise DC4030 controller card, once found.
*/
int
__init
setup_pdc4030
(
ide_hwif_t
*
hwif
)
int
__init
setup_pdc4030
(
ide_hwif_t
*
hwif
)
{
ide_drive_t
*
drive
;
ide_hwif_t
*
hwif2
;
...
...
@@ -168,12 +166,12 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
if
(
hwif
->
chipset
==
ide_pdc4030
)
/* we've already been found ! */
return
1
;
if
(
IN_BYTE
(
IDE_NSECTOR_REG
)
==
0xFF
||
IN_BYTE
(
IDE_SECTOR_REG
)
==
0xFF
)
{
if
(
hwif
->
INB
(
IDE_NSECTOR_REG
)
==
0xFF
||
hwif
->
INB
(
IDE_SECTOR_REG
)
==
0xFF
)
{
return
0
;
}
if
(
IDE_CONTROL_REG
)
OUT_BYTE
(
0x08
,
IDE_CONTROL_REG
);
hwif
->
OUTB
(
0x08
,
IDE_CONTROL_REG
);
if
(
pdc4030_cmd
(
drive
,
PROMISE_GET_CONFIG
))
{
return
0
;
}
...
...
@@ -182,7 +180,7 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
"%s: Failed Promise read config!
\n
"
,
hwif
->
name
);
return
0
;
}
ata_input_data
(
drive
,
&
ident
,
SECTOR_WORDS
);
hwif
->
ata_input_data
(
drive
,
&
ident
,
SECTOR_WORDS
);
if
(
ident
.
id
[
1
]
!=
'P'
||
ident
.
id
[
0
]
!=
'T'
)
{
return
0
;
}
...
...
@@ -226,15 +224,19 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
hwif
->
mate
=
hwif2
;
hwif2
->
mate
=
hwif
;
hwif2
->
channel
=
1
;
hwif
->
rqsize
=
hwif2
->
rqsize
=
127
;
hwif
->
addressing
=
hwif2
->
addressing
=
1
;
hwif
->
selectproc
=
hwif2
->
selectproc
=
&
promise_selectproc
;
hwif
->
serialized
=
hwif2
->
serialized
=
1
;
/* DC4030 hosted drives need their own identify... */
hwif
->
identify
=
hwif2
->
identify
=
&
pdc4030_identify
;
/* Shift the remaining interfaces down
by one */
/* Shift the remaining interfaces up
by one */
for
(
i
=
MAX_HWIFS
-
1
;
i
>
hwif
->
index
+
1
;
i
--
)
{
ide_hwif_t
*
h
=
&
ide_hwifs
[
i
];
#ifdef DEBUG
printk
(
KERN_DEBUG
"Shifting i/f %d values to i/f %d
\n
"
,
i
-
1
,
i
);
printk
(
KERN_DEBUG
"
pdc4030:
Shifting i/f %d values to i/f %d
\n
"
,
i
-
1
,
i
);
#endif
/* DEBUG */
ide_init_hwif_ports
(
&
h
->
hw
,
(
h
-
1
)
->
io_ports
[
IDE_DATA_OFFSET
],
0
,
NULL
);
memcpy
(
h
->
io_ports
,
h
->
hw
.
io_ports
,
sizeof
(
h
->
io_ports
));
...
...
@@ -254,6 +256,11 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
if
(
!
ident
.
current_tm
[
i
+
2
].
cyl
)
hwif2
->
drives
[
i
].
noprobe
=
1
;
}
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init
(
&
ide_hwifs
[
hwif
->
index
]);
probe_hwif_init
(
&
ide_hwifs
[
hwif2
->
index
]);
#endif
/* HWIF_PROBE_CLASSIC_METHOD */
return
1
;
}
...
...
@@ -269,58 +276,152 @@ int __init detect_pdc4030(ide_hwif_t *hwif)
if
(
IDE_DATA_REG
==
0
)
{
/* Skip test for non-existent interface */
return
0
;
}
OUT_BYTE
(
0xF3
,
IDE_SECTOR_REG
);
OUT_BYTE
(
0x14
,
IDE_SELECT_REG
);
OUT_BYTE
(
PROMISE_EXTENDED_COMMAND
,
IDE_COMMAND_REG
);
hwif
->
OUTB
(
0xF3
,
IDE_SECTOR_REG
);
hwif
->
OUTB
(
0x14
,
IDE_SELECT_REG
);
hwif
->
OUTB
(
PROMISE_EXTENDED_COMMAND
,
IDE_COMMAND_REG
);
ide_delay_50ms
();
if
(
IN_BYTE
(
IDE_ERROR_REG
)
==
'P'
&&
IN_BYTE
(
IDE_NSECTOR_REG
)
==
'T'
&&
IN_BYTE
(
IDE_SECTOR_REG
)
==
'I'
)
{
if
(
hwif
->
INB
(
IDE_ERROR_REG
)
==
'P'
&&
hwif
->
INB
(
IDE_NSECTOR_REG
)
==
'T'
&&
hwif
->
INB
(
IDE_SECTOR_REG
)
==
'I'
)
{
return
1
;
}
else
{
return
0
;
}
}
#ifndef MODULE
void
__init
ide_probe_for_pdc4030
(
void
)
#else
int
ide_probe_for_pdc4030
(
void
)
#endif
{
unsigned
int
index
;
ide_hwif_t
*
hwif
;
#ifndef MODULE
if
(
enable_promise_support
==
0
)
return
;
#endif
for
(
index
=
0
;
index
<
MAX_HWIFS
;
index
++
)
{
hwif
=
&
ide_hwifs
[
index
];
if
(
hwif
->
chipset
==
ide_unknown
&&
detect_pdc4030
(
hwif
))
{
#ifndef MODULE
setup_pdc4030
(
hwif
);
#else
return
setup_pdc4030
(
hwif
);
#endif
}
}
#ifdef MODULE
return
0
;
#endif
}
void
__init
release_pdc4030
(
ide_hwif_t
*
hwif
,
ide_hwif_t
*
mate
)
{
hwif
->
chipset
=
ide_unknown
;
hwif
->
selectproc
=
NULL
;
hwif
->
serialized
=
0
;
hwif
->
drives
[
0
].
io_32bit
=
0
;
hwif
->
drives
[
1
].
io_32bit
=
0
;
hwif
->
drives
[
0
].
keep_settings
=
0
;
hwif
->
drives
[
1
].
keep_settings
=
0
;
hwif
->
drives
[
0
].
noprobe
=
0
;
hwif
->
drives
[
1
].
noprobe
=
0
;
if
(
mate
!=
NULL
)
{
mate
->
chipset
=
ide_unknown
;
mate
->
selectproc
=
NULL
;
mate
->
serialized
=
0
;
mate
->
drives
[
0
].
io_32bit
=
0
;
mate
->
drives
[
1
].
io_32bit
=
0
;
mate
->
drives
[
0
].
keep_settings
=
0
;
mate
->
drives
[
1
].
keep_settings
=
0
;
mate
->
drives
[
0
].
noprobe
=
0
;
mate
->
drives
[
1
].
noprobe
=
0
;
}
}
#ifndef MODULE
/*
* init_pdc4030:
*
* called by ide.c when parsing command line
*/
void
__init
init_pdc4030
(
void
)
{
enable_promise_support
=
1
;
}
#else
MODULE_AUTHOR
(
"Peter Denison"
);
MODULE_DESCRIPTION
(
"Support of Promise 4030 VLB series IDE chipsets"
);
MODULE_LICENSE
(
"GPL"
);
int
__init
pdc4030_mod_init
(
void
)
{
if
(
enable_promise_support
==
0
)
enable_promise_support
=
1
;
if
(
!
ide_probe_for_pdc4030
())
return
-
ENODEV
;
return
0
;
}
module_init
(
pdc4030_mod_init
);
void
__init
pdc4030_mod_exit
(
void
)
{
unsigned
int
index
;
ide_hwif_t
*
hwif
;
if
(
enable_promise_support
==
0
)
return
;
for
(
index
=
0
;
index
<
MAX_HWIFS
;
index
++
)
{
hwif
=
&
ide_hwifs
[
index
];
if
(
hwif
->
chipset
==
ide_pdc4030
)
{
ide_hwif_t
*
mate
=
&
ide_hwifs
[
hwif
->
index
+
1
];
if
(
mate
->
chipset
==
ide_pdc4030
)
release_pdc4030
(
hwif
,
mate
);
else
release_pdc4030
(
hwif
,
NULL
);
}
}
enable_promise_support
=
0
;
}
module_exit
(
pdc4030_mod_exit
);
#endif
/*
* promise_read_intr() is the handler for disk read/multread interrupts
*/
static
ide_startstop_t
promise_read_intr
(
ide_drive_t
*
drive
)
{
byte
stat
;
int
total_remaining
;
unsigned
int
sectors_left
,
sectors_avail
,
nsect
;
struct
request
*
rq
;
ata_status_t
status
;
#ifdef CONFIG_IDE_TASKFILE_IO
unsigned
long
flags
;
char
*
to
;
#endif
/* CONFIG_IDE_TASKFILE_IO */
if
(
!
OK_STAT
(
stat
=
GET_STAT
(),
DATA_READY
,
BAD_R_STAT
))
return
DRIVER
(
drive
)
->
error
(
drive
,
"promise_read_intr"
,
stat
);
status
.
all
=
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
);
if
(
!
OK_STAT
(
status
.
all
,
DATA_READY
,
BAD_R_STAT
))
return
DRIVER
(
drive
)
->
error
(
drive
,
"promise_read_intr"
,
status
.
all
);
read_again:
do
{
sectors_left
=
IN_BYTE
(
IDE_NSECTOR_REG
);
IN_BYTE
(
IDE_SECTOR_REG
);
}
while
(
IN_BYTE
(
IDE_NSECTOR_REG
)
!=
sectors_left
);
sectors_left
=
HWIF
(
drive
)
->
INB
(
IDE_NSECTOR_REG
);
HWIF
(
drive
)
->
INB
(
IDE_SECTOR_REG
);
}
while
(
HWIF
(
drive
)
->
INB
(
IDE_NSECTOR_REG
)
!=
sectors_left
);
rq
=
HWGROUP
(
drive
)
->
rq
;
sectors_avail
=
rq
->
nr_sectors
-
sectors_left
;
if
(
!
sectors_avail
)
...
...
@@ -334,9 +435,9 @@ static ide_startstop_t promise_read_intr (ide_drive_t *drive)
sectors_avail
-=
nsect
;
#ifdef CONFIG_IDE_TASKFILE_IO
to
=
ide_map_buffer
(
rq
,
&
flags
);
ata_input_data
(
drive
,
to
,
nsect
*
SECTOR_WORDS
);
HWIF
(
drive
)
->
ata_input_data
(
drive
,
to
,
nsect
*
SECTOR_WORDS
);
#else
/* !CONFIG_IDE_TASKFILE_IO */
ata_input_data
(
drive
,
rq
->
buffer
,
nsect
*
SECTOR_WORDS
);
HWIF
(
drive
)
->
ata_input_data
(
drive
,
rq
->
buffer
,
nsect
*
SECTOR_WORDS
);
#endif
/* CONFIG_IDE_TASKFILE_IO */
#ifdef DEBUG_READ
...
...
@@ -377,13 +478,16 @@ static ide_startstop_t promise_read_intr (ide_drive_t *drive)
if
(
total_remaining
>
0
)
{
if
(
sectors_avail
)
goto
read_next
;
stat
=
GET_STAT
(
);
if
(
stat
&
DRQ_STAT
)
stat
us
.
all
=
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
);
if
(
stat
us
.
b
.
drq
)
goto
read_again
;
if
(
stat
&
BUSY_STAT
)
{
if
(
HWGROUP
(
drive
)
->
handler
!=
NULL
)
/* paranoia check */
if
(
stat
us
.
b
.
bsy
)
{
if
(
HWGROUP
(
drive
)
->
handler
!=
NULL
)
BUG
();
ide_set_handler
(
drive
,
&
promise_read_intr
,
WAIT_CMD
,
NULL
);
ide_set_handler
(
drive
,
&
promise_read_intr
,
WAIT_CMD
,
NULL
);
#ifdef DEBUG_READ
printk
(
KERN_DEBUG
"%s: promise_read: waiting for"
"interrupt
\n
"
,
drive
->
name
);
...
...
@@ -392,7 +496,8 @@ static ide_startstop_t promise_read_intr (ide_drive_t *drive)
}
printk
(
KERN_ERR
"%s: Eeek! promise_read_intr: sectors left "
"!DRQ !BUSY
\n
"
,
drive
->
name
);
return
DRIVER
(
drive
)
->
error
(
drive
,
"promise read intr"
,
stat
);
return
DRIVER
(
drive
)
->
error
(
drive
,
"promise read intr"
,
status
.
all
);
}
return
ide_stopped
;
}
...
...
@@ -411,17 +516,21 @@ static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
struct
request
*
rq
=
hwgroup
->
rq
;
int
i
;
if
(
GET_STAT
(
)
&
BUSY_STAT
)
{
if
(
(
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
)
)
&
BUSY_STAT
)
{
if
(
time_before
(
jiffies
,
hwgroup
->
poll_timeout
))
{
if
(
HWGROUP
(
drive
)
->
handler
!=
NULL
)
/* paranoia check */
if
(
hwgroup
->
handler
!=
NULL
)
BUG
();
ide_set_handler
(
drive
,
&
promise_complete_pollfunc
,
HZ
/
100
,
NULL
);
ide_set_handler
(
drive
,
&
promise_complete_pollfunc
,
HZ
/
100
,
NULL
);
return
ide_started
;
/* continue polling... */
}
hwgroup
->
poll_timeout
=
0
;
printk
(
KERN_ERR
"%s: completion timeout - still busy!
\n
"
,
drive
->
name
);
return
DRIVER
(
drive
)
->
error
(
drive
,
"busy timeout"
,
GET_STAT
());
return
DRIVER
(
drive
)
->
error
(
drive
,
"busy timeout"
,
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
));
}
hwgroup
->
poll_timeout
=
0
;
...
...
@@ -475,24 +584,16 @@ int promise_multwrite (ide_drive_t *drive, unsigned int mcount)
/* Do we move to the next bh after this? */
if
(
!
rq
->
current_nr_sectors
)
{
struct
bio
*
bio
=
rq
->
bio
;
/*
* only move to next bio, when we have processed
* all bvecs in this one.
*/
if
(
++
bio
->
bi_idx
>=
bio
->
bi_vcnt
)
{
bio
->
bi_idx
=
0
;
bio
=
bio
->
bi_next
;
}
struct
buffer_head
*
bh
=
rq
->
bh
->
b_reqnext
;
/* end early early we ran out of requests */
if
(
!
b
io
)
{
if
(
!
b
h
)
{
mcount
=
0
;
}
else
{
rq
->
b
io
=
bio
;
rq
->
current_nr_sectors
=
bio_iovec
(
bio
)
->
bv_len
>>
9
;
rq
->
b
h
=
bh
;
rq
->
current_nr_sectors
=
bh
->
b_size
>>
9
;
rq
->
hard_cur_sectors
=
rq
->
current_nr_sectors
;
rq
->
buffer
=
bh
->
b_data
;
}
}
...
...
@@ -516,16 +617,20 @@ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
{
ide_hwgroup_t
*
hwgroup
=
HWGROUP
(
drive
);
if
(
IN_BYTE
(
IDE_NSECTOR_REG
)
!=
0
)
{
if
(
HWIF
(
drive
)
->
INB
(
IDE_NSECTOR_REG
)
!=
0
)
{
if
(
time_before
(
jiffies
,
hwgroup
->
poll_timeout
))
{
if
(
HWGROUP
(
drive
)
->
handler
!=
NULL
)
/* paranoia check */
if
(
hwgroup
->
handler
!=
NULL
)
BUG
();
ide_set_handler
(
drive
,
&
promise_write_pollfunc
,
HZ
/
100
,
NULL
);
ide_set_handler
(
drive
,
&
promise_write_pollfunc
,
HZ
/
100
,
NULL
);
return
ide_started
;
/* continue polling... */
}
hwgroup
->
poll_timeout
=
0
;
printk
(
KERN_ERR
"%s: write timed-out!
\n
"
,
drive
->
name
);
return
DRIVER
(
drive
)
->
error
(
drive
,
"write timeout"
,
GET_STAT
());
return
DRIVER
(
drive
)
->
error
(
drive
,
"write timeout"
,
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
));
}
/*
...
...
@@ -533,12 +638,12 @@ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
*/
promise_multwrite
(
drive
,
4
);
hwgroup
->
poll_timeout
=
jiffies
+
WAIT_WORSTCASE
;
if
(
HWGROUP
(
drive
)
->
handler
!=
NULL
)
/* paranoia check */
if
(
hwgroup
->
handler
!=
NULL
)
BUG
();
ide_set_handler
(
drive
,
&
promise_complete_pollfunc
,
HZ
/
100
,
NULL
);
#ifdef DEBUG_WRITE
printk
(
KERN_DEBUG
"%s: Done last 4 sectors - status = %02x
\n
"
,
drive
->
name
,
GET_STAT
(
));
drive
->
name
,
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
));
#endif
/* DEBUG_WRITE */
return
ide_started
;
}
...
...
@@ -569,7 +674,7 @@ static ide_startstop_t promise_write (ide_drive_t *drive)
if
(
promise_multwrite
(
drive
,
rq
->
nr_sectors
-
4
))
return
ide_stopped
;
hwgroup
->
poll_timeout
=
jiffies
+
WAIT_WORSTCASE
;
if
(
HWGROUP
(
drive
)
->
handler
!=
NULL
)
/* paranoia check */
if
(
hwgroup
->
handler
!=
NULL
)
/* paranoia check */
BUG
();
ide_set_handler
(
drive
,
&
promise_write_pollfunc
,
HZ
/
100
,
NULL
);
return
ide_started
;
...
...
@@ -581,19 +686,24 @@ static ide_startstop_t promise_write (ide_drive_t *drive)
if
(
promise_multwrite
(
drive
,
rq
->
nr_sectors
))
return
ide_stopped
;
hwgroup
->
poll_timeout
=
jiffies
+
WAIT_WORSTCASE
;
if
(
HWGROUP
(
drive
)
->
handler
!=
NULL
)
/* paranoia check */
if
(
hwgroup
->
handler
!=
NULL
)
BUG
();
ide_set_handler
(
drive
,
&
promise_complete_pollfunc
,
HZ
/
100
,
NULL
);
ide_set_handler
(
drive
,
&
promise_complete_pollfunc
,
HZ
/
100
,
NULL
);
#ifdef DEBUG_WRITE
printk
(
KERN_DEBUG
"%s: promise_write: <= 4 sectors, "
"status = %02x
\n
"
,
drive
->
name
,
GET_STAT
());
"status = %02x
\n
"
,
drive
->
name
,
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
));
#endif
/* DEBUG_WRITE */
return
ide_started
;
}
}
/*
* do_pdc4030_io() is called from
do
_rw_disk, having had the block number
* do_pdc4030_io() is called from
promise
_rw_disk, having had the block number
* already set up. It issues a READ or WRITE command to the Promise
* controller, assuming LBA has been used to set up the block number.
*/
...
...
@@ -608,29 +718,27 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
#endif
/* CONFIG_IDE_TASKFILE_IO */
ide_startstop_t
startstop
;
unsigned
long
timeout
;
byte
stat
;
BUG_ON
(
!
(
rq
->
flags
&
REQ_CMD
));
u8
stat
=
0
;
#ifdef CONFIG_IDE_TASKFILE_IO
if
(
IDE_CONTROL_REG
)
OUT_BYTE
(
drive
->
ctl
,
IDE_CONTROL_REG
);
/* clear nIEN */
SELECT_MASK
(
HWIF
(
drive
),
drive
,
0
);
OUT_BYTE
(
taskfile
->
feature
,
IDE_FEATURE_REG
);
OUT_BYTE
(
taskfile
->
sector_count
,
IDE_NSECTOR_REG
);
HWIF
(
drive
)
->
OUTB
(
drive
->
ctl
,
IDE_CONTROL_REG
);
/* clear nIEN */
SELECT_MASK
(
drive
,
0
);
HWIF
(
drive
)
->
OUTB
(
taskfile
->
feature
,
IDE_FEATURE_REG
);
HWIF
(
drive
)
->
OUTB
(
taskfile
->
sector_count
,
IDE_NSECTOR_REG
);
/* refers to number of sectors to transfer */
OUT_BYTE
(
taskfile
->
sector_number
,
IDE_SECTOR_REG
);
HWIF
(
drive
)
->
OUTB
(
taskfile
->
sector_number
,
IDE_SECTOR_REG
);
/* refers to sector offset or start sector */
OUT_BYTE
(
taskfile
->
low_cylinder
,
IDE_LCYL_REG
);
OUT_BYTE
(
taskfile
->
high_cylinder
,
IDE_HCYL_REG
);
OUT_BYTE
(
taskfile
->
device_head
,
IDE_SELECT_REG
);
OUT_BYTE
(
taskfile
->
command
,
IDE_COMMAND_REG
);
HWIF
(
drive
)
->
OUTB
(
taskfile
->
low_cylinder
,
IDE_LCYL_REG
);
HWIF
(
drive
)
->
OUTB
(
taskfile
->
high_cylinder
,
IDE_HCYL_REG
);
HWIF
(
drive
)
->
OUTB
(
taskfile
->
device_head
,
IDE_SELECT_REG
);
HWIF
(
drive
)
->
OUTB
(
taskfile
->
command
,
IDE_COMMAND_REG
);
#endif
/* CONFIG_IDE_TASKFILE_IO */
if
(
rq_data_dir
(
rq
)
==
READ
)
{
switch
(
rq
->
cmd
)
{
case
READ
:
#ifndef CONFIG_IDE_TASKFILE_IO
OUT_BYTE
(
PROMISE_READ
,
IDE_COMMAND_REG
);
HWIF
(
drive
)
->
OUTB
(
PROMISE_READ
,
IDE_COMMAND_REG
);
#endif
/* CONFIG_IDE_TASKFILE_IO */
/*
* The card's behaviour is odd at this point. If the data is
...
...
@@ -644,17 +752,20 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
*/
timeout
=
jiffies
+
HZ
/
20
;
/* 50ms wait */
do
{
stat
=
GET_STAT
(
);
stat
=
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
);
if
(
stat
&
DRQ_STAT
)
{
udelay
(
1
);
return
promise_read_intr
(
drive
);
}
if
(
IN_BYTE
(
IDE_SELECT_REG
)
&
0x01
)
{
if
(
HWIF
(
drive
)
->
INB
(
IDE_SELECT_REG
)
&
0x01
)
{
#ifdef DEBUG_READ
printk
(
KERN_DEBUG
"%s: read: waiting for "
"interrupt
\n
"
,
drive
->
name
);
#endif
/* DEBUG_READ */
ide_set_handler
(
drive
,
&
promise_read_intr
,
WAIT_CMD
,
NULL
);
ide_set_handler
(
drive
,
&
promise_read_intr
,
WAIT_CMD
,
NULL
);
return
ide_started
;
}
udelay
(
1
);
...
...
@@ -663,9 +774,9 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
printk
(
KERN_ERR
"%s: reading: No DRQ and not "
"waiting - Odd!
\n
"
,
drive
->
name
);
return
ide_stopped
;
}
else
if
(
rq_data_dir
(
rq
)
==
WRITE
)
{
case
WRITE
:
#ifndef CONFIG_IDE_TASKFILE_IO
OUT_BYTE
(
PROMISE_WRITE
,
IDE_COMMAND_REG
);
HWIF
(
drive
)
->
OUTB
(
PROMISE_WRITE
,
IDE_COMMAND_REG
);
#endif
/* CONFIG_IDE_TASKFILE_IO */
if
(
ide_wait_stat
(
&
startstop
,
drive
,
DATA_READY
,
drive
->
bad_wstat
,
WAIT_DRQ
))
{
...
...
@@ -677,22 +788,53 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
local_irq_disable
();
HWGROUP
(
drive
)
->
wrq
=
*
rq
;
/* scratchpad */
return
promise_write
(
drive
);
}
else
{
blk_dump_rq_flags
(
rq
,
"do_pdc4030_io - bad command
\n
"
);
default:
printk
(
"KERN_WARNING %s: bad command: %d
\n
"
,
drive
->
name
,
rq
->
cmd
);
DRIVER
(
drive
)
->
end_request
(
drive
,
0
);
return
ide_stopped
;
}
}
#ifdef CONFIG_IDE_TASKFILE_IO
ide_startstop_t
promise_rw_disk
(
ide_drive_t
*
drive
,
struct
request
*
rq
,
unsigned
long
block
)
{
/* The four drives on the two logical (one physical) interfaces
are distinguished by writing the drive number (0-3) to the
Feature register.
FIXME: Is promise_selectproc now redundant??
*/
int
drive_number
=
(
HWIF
(
drive
)
->
channel
<<
1
)
+
drive
->
select
.
b
.
unit
;
#ifndef CONFIG_IDE_TASKFILE_IO
ide_hwif_t
*
hwif
=
HWIF
(
drive
);
BUG_ON
(
rq
->
nr_sectors
>
127
);
if
(
IDE_CONTROL_REG
)
hwif
->
OUTB
(
drive
->
ctl
,
IDE_CONTROL_REG
);
#ifdef DEBUG
printk
(
"%s: %sing: LBAsect=%ld, sectors=%ld, "
"buffer=0x%08lx
\n
"
,
drive
->
name
,
(
rq
->
cmd
==
READ
)
?
"read"
:
"writ"
,
block
,
rq
->
nr_sectors
,
(
unsigned
long
)
rq
->
buffer
);
#endif
hwif
->
OUTB
(
drive_number
,
IDE_FEATURE_REG
);
hwif
->
OUTB
(
rq
->
nr_sectors
,
IDE_NSECTOR_REG
);
hwif
->
OUTB
(
block
,
IDE_SECTOR_REG
);
hwif
->
OUTB
(
block
>>=
8
,
IDE_LCYL_REG
);
hwif
->
OUTB
(
block
>>=
8
,
IDE_HCYL_REG
);
hwif
->
OUTB
(((
block
>>
8
)
&
0x0f
)
|
drive
->
select
.
all
,
IDE_SELECT_REG
);
return
do_pdc4030_io
(
drive
,
rq
);
#else
/* CONFIG_IDE_TASKFILE_IO */
struct
hd_drive_task_hdr
taskfile
;
ide_task_t
args
;
memset
(
&
taskfile
,
0
,
sizeof
(
struct
hd_drive_task_hdr
));
taskfile
.
feature
=
drive_number
;
taskfile
.
sector_count
=
rq
->
nr_sectors
;
taskfile
.
sector_number
=
block
;
taskfile
.
low_cylinder
=
(
block
>>=
8
);
...
...
@@ -701,16 +843,16 @@ ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigne
taskfile
.
command
=
(
rq
->
cmd
==
READ
)
?
PROMISE_READ
:
PROMISE_WRITE
;
memcpy
(
args
.
tfRegister
,
&
taskfile
,
sizeof
(
struct
hd_drive_task_hdr
));
memcpy
(
args
.
hobRegister
,
NULL
,
sizeof
(
struct
hd_drive_hob_hdr
));
args
.
command_type
=
ide_cmd_type_parser
(
&
args
);
args
.
prehandler
=
NULL
;
memset
(
args
.
hobRegister
,
0
,
sizeof
(
struct
hd_drive_hob_hdr
));
/* We can't call ide_cmd_type_parser here, since it won't understand
our command, but that doesn't matter, since we don't use the
generic interrupt handlers either. Setup the bits of args that we
do need.
*/
args
.
handler
=
NULL
;
args
.
posthandler
=
NULL
;
args
.
rq
=
(
struct
request
*
)
rq
;
rq
->
special
=
NULL
;
rq
->
special
=
(
ide_task_t
*
)
&
args
;
return
do_pdc4030_io
(
drive
,
&
args
);
}
#endif
/* CONFIG_IDE_TASKFILE_IO */
}
drivers/ide/legacy/q40ide.c
View file @
26af05ea
...
...
@@ -84,7 +84,9 @@ void q40ide_init(void)
ide_setup_ports
(
&
hw
,(
ide_ioreg_t
)
pcide_bases
[
i
],
(
int
*
)
pcide_offsets
,
pcide_bases
[
i
]
+
0x206
,
0
,
NULL
,
q40ide_default_irq
(
pcide_bases
[
i
]));
0
,
NULL
,
// pcide_iops,
q40ide_default_irq
(
pcide_bases
[
i
]));
ide_register_hw
(
&
hw
,
NULL
);
}
}
...
...
drivers/ide/legacy/qd65xx.c
View file @
26af05ea
...
...
@@ -27,6 +27,8 @@
#undef REALLY_SLOW_IO
/* most systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
...
...
@@ -37,9 +39,17 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_QD65XX_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif
/* CONFIG_BLK_DEV_QD65XX_MODULE */
#include "qd65xx.h"
/*
...
...
@@ -85,27 +95,27 @@
* bit 5 : status, but of what ?
* bit 6 : always set 1 by dos driver
* bit 7 : set 1 for non-ATAPI devices on primary port
*
(maybe read-ahead and post-write buffer ?)
* (maybe read-ahead and post-write buffer ?)
*/
static
int
timings
[
4
]
=
{
-
1
,
-
1
,
-
1
,
-
1
};
/* stores current timing for each timer */
static
void
qd_write_reg
(
byte
content
,
byte
reg
)
static
void
qd_write_reg
(
u8
content
,
u8
reg
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
ide_lock
,
flags
);
OUT_BYTE
(
content
,
reg
);
outb
(
content
,
reg
);
spin_unlock_irqrestore
(
&
ide_lock
,
flags
);
}
byte
__init
qd_read_reg
(
byte
reg
)
u8
__init
qd_read_reg
(
u8
reg
)
{
unsigned
long
flags
;
byte
read
;
u8
read
;
spin_lock_irqsave
(
&
ide_lock
,
flags
);
read
=
IN_BYTE
(
reg
);
read
=
inb
(
reg
);
spin_unlock_irqrestore
(
&
ide_lock
,
flags
);
return
read
;
}
...
...
@@ -118,7 +128,7 @@ byte __init qd_read_reg (byte reg)
static
void
qd_select
(
ide_drive_t
*
drive
)
{
byte
index
=
((
(
QD_TIMREG
(
drive
))
&
0x80
)
>>
7
)
|
u8
index
=
((
(
QD_TIMREG
(
drive
))
&
0x80
)
>>
7
)
|
(
QD_TIMREG
(
drive
)
&
0x02
);
if
(
timings
[
index
]
!=
QD_TIMING
(
drive
))
...
...
@@ -129,20 +139,20 @@ static void qd_select (ide_drive_t *drive)
* qd6500_compute_timing
*
* computes the timing value where
*
lower nibble represents active time, in count of VLB clocks
*
upper nibble represents recovery time, in count of VLB clocks
* lower nibble represents active time, in count of VLB clocks
* upper nibble represents recovery time, in count of VLB clocks
*/
static
byte
qd6500_compute_timing
(
ide_hwif_t
*
hwif
,
int
active_time
,
int
recovery_time
)
static
u8
qd6500_compute_timing
(
ide_hwif_t
*
hwif
,
int
active_time
,
int
recovery_time
)
{
byte
active_cycle
,
recovery_cycle
;
u8
active_cycle
,
recovery_cycle
;
if
(
ide_system_bus_speed
()
<=
33
)
{
active_cycle
=
9
-
IDE_IN
(
active_time
*
ide_system_bus_speed
()
/
1000
+
1
,
2
,
9
);
recovery_cycle
=
15
-
IDE_IN
(
recovery_time
*
ide_system_bus_speed
()
/
1000
+
1
,
0
,
15
);
if
(
system_bus_clock
()
<=
33
)
{
active_cycle
=
9
-
IDE_IN
(
active_time
*
system_bus_clock
()
/
1000
+
1
,
2
,
9
);
recovery_cycle
=
15
-
IDE_IN
(
recovery_time
*
system_bus_clock
()
/
1000
+
1
,
0
,
15
);
}
else
{
active_cycle
=
8
-
IDE_IN
(
active_time
*
ide_system_bus_speed
()
/
1000
+
1
,
1
,
8
);
recovery_cycle
=
18
-
IDE_IN
(
recovery_time
*
ide_system_bus_speed
()
/
1000
+
1
,
3
,
18
);
active_cycle
=
8
-
IDE_IN
(
active_time
*
system_bus_clock
()
/
1000
+
1
,
1
,
8
);
recovery_cycle
=
18
-
IDE_IN
(
recovery_time
*
system_bus_clock
()
/
1000
+
1
,
3
,
18
);
}
return
((
recovery_cycle
<<
4
)
|
0x08
|
active_cycle
);
...
...
@@ -154,10 +164,10 @@ static byte qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recove
* idem for qd6580
*/
static
byte
qd6580_compute_timing
(
int
active_time
,
int
recovery_time
)
static
u8
qd6580_compute_timing
(
int
active_time
,
int
recovery_time
)
{
byte
active_cycle
=
17
-
IDE_IN
(
active_time
*
ide_system_bus_speed
()
/
1000
+
1
,
2
,
17
);
byte
recovery_cycle
=
15
-
IDE_IN
(
recovery_time
*
ide_system_bus_speed
()
/
1000
+
1
,
2
,
15
);
u8
active_cycle
=
17
-
IDE_IN
(
active_time
*
system_bus_clock
()
/
1000
+
1
,
2
,
17
);
u8
recovery_cycle
=
15
-
IDE_IN
(
recovery_time
*
system_bus_clock
()
/
1000
+
1
,
2
,
15
);
return
((
recovery_cycle
<<
4
)
|
active_cycle
);
}
...
...
@@ -180,8 +190,8 @@ static int qd_find_disk_type (ide_drive_t *drive,
ide_fixstring
(
model
,
40
,
1
);
/* byte-swap */
for
(
p
=
qd65xx_timing
;
p
->
offset
!=
-
1
;
p
++
)
{
if
(
!
strncmp
(
p
->
model
,
model
+
p
->
offset
,
4
))
{
printk
(
KERN_DEBUG
"%s: listed !
\n
"
,
drive
->
name
);
if
(
!
strncmp
(
p
->
model
,
model
+
p
->
offset
,
4
))
{
printk
(
KERN_DEBUG
"%s: listed !
\n
"
,
drive
->
name
);
*
active_time
=
p
->
active
;
*
recovery_time
=
p
->
recovery
;
return
1
;
...
...
@@ -210,7 +220,7 @@ static int qd_timing_ok (ide_drive_t drives[])
* records the timing, and enables selectproc as needed
*/
static
void
qd_set_timing
(
ide_drive_t
*
drive
,
byte
timing
)
static
void
qd_set_timing
(
ide_drive_t
*
drive
,
u8
timing
)
{
ide_hwif_t
*
hwif
=
HWIF
(
drive
);
...
...
@@ -222,19 +232,19 @@ static void qd_set_timing (ide_drive_t *drive, byte timing)
}
else
hwif
->
selectproc
=
&
qd_select
;
printk
(
KERN_DEBUG
"%s: %#x
\n
"
,
drive
->
name
,
timing
);
printk
(
KERN_DEBUG
"%s: %#x
\n
"
,
drive
->
name
,
timing
);
}
/*
* qd6500_tune_drive
*/
static
void
qd6500_tune_drive
(
ide_drive_t
*
drive
,
byte
pio
)
static
void
qd6500_tune_drive
(
ide_drive_t
*
drive
,
u8
pio
)
{
int
active_time
=
175
;
int
recovery_time
=
415
;
/* worst case values from the dos driver */
if
(
drive
->
id
&&
!
qd_find_disk_type
(
drive
,
&
active_time
,
&
recovery_time
)
if
(
drive
->
id
&&
!
qd_find_disk_type
(
drive
,
&
active_time
,
&
recovery_time
)
&&
drive
->
id
->
tPIO
&&
(
drive
->
id
->
field_valid
&
0x02
)
&&
drive
->
id
->
eide_pio
>=
240
)
{
...
...
@@ -244,21 +254,21 @@ static void qd6500_tune_drive (ide_drive_t *drive, byte pio)
recovery_time
=
drive
->
id
->
eide_pio
-
120
;
}
qd_set_timing
(
drive
,
qd6500_compute_timing
(
HWIF
(
drive
),
active_time
,
recovery_time
));
qd_set_timing
(
drive
,
qd6500_compute_timing
(
HWIF
(
drive
),
active_time
,
recovery_time
));
}
/*
* qd6580_tune_drive
*/
static
void
qd6580_tune_drive
(
ide_drive_t
*
drive
,
byte
pio
)
static
void
qd6580_tune_drive
(
ide_drive_t
*
drive
,
u8
pio
)
{
ide_pio_data_t
d
;
int
base
=
HWIF
(
drive
)
->
select_data
;
int
active_time
=
175
;
int
recovery_time
=
415
;
/* worst case values from the dos driver */
if
(
drive
->
id
&&
!
qd_find_disk_type
(
drive
,
&
active_time
,
&
recovery_time
))
{
if
(
drive
->
id
&&
!
qd_find_disk_type
(
drive
,
&
active_time
,
&
recovery_time
))
{
pio
=
ide_get_best_pio_mode
(
drive
,
pio
,
255
,
&
d
);
pio
=
IDE_MIN
(
pio
,
4
);
...
...
@@ -267,14 +277,14 @@ static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
case
3
:
if
(
d
.
cycle_time
>=
110
)
{
active_time
=
86
;
recovery_time
=
d
.
cycle_time
-
102
;
recovery_time
=
d
.
cycle_time
-
102
;
}
else
printk
(
KERN_WARNING
"%s: Strange recovery time !
\n
"
,
drive
->
name
);
break
;
case
4
:
if
(
d
.
cycle_time
>=
69
)
{
active_time
=
70
;
recovery_time
=
d
.
cycle_time
-
61
;
recovery_time
=
d
.
cycle_time
-
61
;
}
else
printk
(
KERN_WARNING
"%s: Strange recovery time !
\n
"
,
drive
->
name
);
break
;
...
...
@@ -288,15 +298,17 @@ static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
-
active_time
;
}
}
printk
(
KERN_INFO
"%s: PIO mode%d
\n
"
,
drive
->
name
,
pio
);
printk
(
KERN_INFO
"%s: PIO mode%d
\n
"
,
drive
->
name
,
pio
);
}
if
(
!
HWIF
(
drive
)
->
channel
&&
drive
->
media
!=
ide_disk
)
{
qd_write_reg
(
0x5f
,
QD_CONTROL_PORT
);
printk
(
KERN_WARNING
"%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.
\n
"
,
drive
->
name
,
HWIF
(
drive
)
->
name
);
qd_write_reg
(
0x5f
,
QD_CONTROL_PORT
);
printk
(
KERN_WARNING
"%s: ATAPI: disabled read-ahead FIFO "
"and post-write buffer on %s.
\n
"
,
drive
->
name
,
HWIF
(
drive
)
->
name
);
}
qd_set_timing
(
drive
,
qd6580_compute_timing
(
active_time
,
recovery_time
));
qd_set_timing
(
drive
,
qd6580_compute_timing
(
active_time
,
recovery_time
));
}
/*
...
...
@@ -307,15 +319,15 @@ static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
static
int
__init
qd_testreg
(
int
port
)
{
byte
savereg
;
byte
readreg
;
u8
savereg
;
u8
readreg
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
ide_lock
,
flags
);
savereg
=
inb_p
(
port
);
outb_p
(
QD_TESTVAL
,
port
);
/* safe value */
outb_p
(
QD_TESTVAL
,
port
);
/* safe value */
readreg
=
inb_p
(
port
);
OUT_BYTE
(
savereg
,
port
);
outb
(
savereg
,
port
);
spin_unlock_irqrestore
(
&
ide_lock
,
flags
);
if
(
savereg
==
QD_TESTVAL
)
{
...
...
@@ -329,32 +341,91 @@ static int __init qd_testreg(int port)
}
/*
* probe:
* qd_setup:
*
* called to setup an ata channel : adjusts attributes & links for tuning
*/
void
__init
qd_setup
(
int
unit
,
int
base
,
int
config
,
unsigned
int
data0
,
unsigned
int
data1
,
void
(
*
tuneproc
)
(
ide_drive_t
*
,
u8
pio
))
{
ide_hwif_t
*
hwif
=
&
ide_hwifs
[
unit
];
hwif
->
chipset
=
ide_qd65xx
;
hwif
->
channel
=
unit
;
hwif
->
select_data
=
base
;
hwif
->
config_data
=
config
;
hwif
->
drives
[
0
].
drive_data
=
data0
;
hwif
->
drives
[
1
].
drive_data
=
data1
;
hwif
->
drives
[
0
].
io_32bit
=
hwif
->
drives
[
1
].
io_32bit
=
1
;
hwif
->
tuneproc
=
tuneproc
;
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init
(
hwif
);
#endif
/* HWIF_PROBE_CLASSIC_METHOD */
}
/*
* qd_unsetup:
*
* called to unsetup an ata channel : back to default values, unlinks tuning
*/
void
__init
qd_unsetup
(
int
unit
)
{
ide_hwif_t
*
hwif
=
&
ide_hwifs
[
unit
];
u8
config
=
hwif
->
config_data
;
int
base
=
hwif
->
select_data
;
void
*
tuneproc
=
(
void
*
)
hwif
->
tuneproc
;
if
(
!
(
hwif
->
chipset
==
ide_qd65xx
))
return
;
printk
(
KERN_NOTICE
"%s: back to defaults
\n
"
,
hwif
->
name
);
hwif
->
selectproc
=
NULL
;
hwif
->
tuneproc
=
NULL
;
if
(
tuneproc
==
(
void
*
)
qd6500_tune_drive
)
{
// will do it for both
qd_write_reg
(
QD6500_DEF_DATA
,
QD_TIMREG
(
&
hwif
->
drives
[
0
]));
}
else
if
(
tuneproc
==
(
void
*
)
qd6580_tune_drive
)
{
if
(
QD_CONTROL
(
hwif
)
&
QD_CONTR_SEC_DISABLED
)
{
qd_write_reg
(
QD6580_DEF_DATA
,
QD_TIMREG
(
&
hwif
->
drives
[
0
]));
qd_write_reg
(
QD6580_DEF_DATA2
,
QD_TIMREG
(
&
hwif
->
drives
[
1
]));
}
else
{
qd_write_reg
(
unit
?
QD6580_DEF_DATA2
:
QD6580_DEF_DATA
,
QD_TIMREG
(
&
hwif
->
drives
[
0
]));
}
}
else
{
printk
(
KERN_WARNING
"Unknown qd65xx tuning fonction !
\n
"
);
printk
(
KERN_WARNING
"keeping settings !
\n
"
);
}
}
/*
* qd_probe:
*
* looks at the specified baseport, and if qd found, registers & initialises it
* return 1 if another qd may be probed
*/
int
__init
probe
(
int
base
)
int
__init
qd_
probe
(
int
base
)
{
byte
config
;
byte
index
;
u8
config
;
u8
unit
;
config
=
qd_read_reg
(
QD_CONFIG_PORT
);
if
(
!
((
config
&
QD_CONFIG_BASEPORT
)
>>
1
==
(
base
==
0xb0
))
)
return
1
;
if
(
!
((
config
&
QD_CONFIG_BASEPORT
)
>>
1
==
(
base
==
0xb0
))
)
return
1
;
index
=
!
(
config
&
QD_CONFIG_IDE_BASEPORT
);
unit
=
!
(
config
&
QD_CONFIG_IDE_BASEPORT
);
if
((
config
&
0xf0
)
==
QD_CONFIG_QD6500
)
{
ide_hwif_t
*
hwif
=
&
ide_hwifs
[
index
];
if
(
qd_testreg
(
base
))
return
1
;
/* bad register */
/* qd6500 found */
/* qd6500 found */
printk
(
KERN_NOTICE
"%s: qd6500 at %#x
\n
"
,
ide_hwifs
[
index
].
name
,
base
);
ide_hwifs
[
unit
].
name
,
base
);
printk
(
KERN_DEBUG
"qd6500: config=%#x, ID3=%u
\n
"
,
config
,
QD_ID3
);
...
...
@@ -364,25 +435,20 @@ int __init probe (int base)
return
1
;
}
hwif
->
chipset
=
ide_qd65xx
;
hwif
->
select_data
=
base
;
hwif
->
config_data
=
config
;
hwif
->
drives
[
0
].
drive_data
=
hwif
->
drives
[
1
].
drive_data
=
QD6500_DEF_DATA
;
hwif
->
drives
[
0
].
io_32bit
=
hwif
->
drives
[
1
].
io_32bit
=
1
;
hwif
->
tuneproc
=
&
qd6500_tune_drive
;
qd_setup
(
unit
,
base
,
config
,
QD6500_DEF_DATA
,
QD6500_DEF_DATA
,
&
qd6500_tune_drive
);
return
1
;
}
if
(((
config
&
0xf0
)
==
QD_CONFIG_QD6580_A
)
||
((
config
&
0xf0
)
==
QD_CONFIG_QD6580_B
))
{
if
(((
config
&
0xf0
)
==
QD_CONFIG_QD6580_A
)
||
((
config
&
0xf0
)
==
QD_CONFIG_QD6580_B
))
{
byte
control
;
u8
control
;
if
(
qd_testreg
(
base
)
||
qd_testreg
(
base
+
0x02
))
return
1
;
/* bad registers */
/* qd6580 found */
/* qd6580 found */
control
=
qd_read_reg
(
QD_CONTROL_PORT
);
...
...
@@ -391,47 +457,26 @@ int __init probe (int base)
config
,
control
,
QD_ID3
);
if
(
control
&
QD_CONTR_SEC_DISABLED
)
{
ide_hwif_t
*
hwif
=
&
ide_hwifs
[
index
];
/* secondary disabled */
printk
(
KERN_INFO
"%s: qd6580: single IDE board
\n
"
,
ide_hwifs
[
index
].
name
);
hwif
->
chipset
=
ide_qd65xx
;
hwif
->
select_data
=
base
;
hwif
->
config_data
=
config
|
(
control
<<
8
);
hwif
->
drives
[
0
].
drive_data
=
hwif
->
drives
[
1
].
drive_data
=
QD6580_DEF_DATA
;
hwif
->
drives
[
0
].
io_32bit
=
hwif
->
drives
[
1
].
io_32bit
=
1
;
hwif
->
tuneproc
=
&
qd6580_tune_drive
;
ide_hwifs
[
unit
].
name
);
qd_setup
(
unit
,
base
,
config
|
(
control
<<
8
),
QD6580_DEF_DATA
,
QD6580_DEF_DATA2
,
&
qd6580_tune_drive
);
qd_write_reg
(
QD_DEF_CONTR
,
QD_CONTROL_PORT
);
return
1
;
}
else
{
int
i
,
j
;
/* secondary enabled */
printk
(
KERN_INFO
"%s&%s: qd6580: dual IDE board
\n
"
,
ide_hwifs
[
0
].
name
,
ide_hwifs
[
1
].
name
);
for
(
i
=
0
;
i
<
2
;
i
++
)
{
ide_hwifs
[
i
].
chipset
=
ide_qd65xx
;
ide_hwifs
[
i
].
mate
=
&
ide_hwifs
[
i
^
1
];
ide_hwifs
[
i
].
channel
=
i
;
ide_hwifs
[
i
].
select_data
=
base
;
ide_hwifs
[
i
].
config_data
=
config
|
(
control
<<
8
);
ide_hwifs
[
i
].
tuneproc
=
&
qd6580_tune_drive
;
for
(
j
=
0
;
j
<
2
;
j
++
)
{
ide_hwifs
[
i
].
drives
[
j
].
drive_data
=
i
?
QD6580_DEF_DATA2
:
QD6580_DEF_DATA
;
ide_hwifs
[
i
].
drives
[
j
].
io_32bit
=
1
;
}
}
qd_setup
(
0
,
base
,
config
|
(
control
<<
8
),
QD6580_DEF_DATA
,
QD6580_DEF_DATA
,
&
qd6580_tune_drive
);
qd_setup
(
1
,
base
,
config
|
(
control
<<
8
),
QD6580_DEF_DATA2
,
QD6580_DEF_DATA2
,
&
qd6580_tune_drive
);
qd_write_reg
(
QD_DEF_CONTR
,
QD_CONTROL_PORT
);
return
0
;
/* no other qd65xx possible */
...
...
@@ -441,13 +486,38 @@ int __init probe (int base)
return
1
;
}
#ifndef MODULE
/*
* init_qd65xx:
*
* called
at the very beginning of initialization ; should just probe and link
* called
by ide.c when parsing command line
*/
void
__init
init_qd65xx
(
void
)
{
if
(
probe
(
0x30
))
probe
(
0xb0
);
if
(
qd_probe
(
0x30
))
qd_probe
(
0xb0
);
}
#else
MODULE_AUTHOR
(
"Samuel Thibault"
);
MODULE_DESCRIPTION
(
"support of qd65xx vlb ide chipset"
);
MODULE_LICENSE
(
"GPL"
);
int
__init
qd65xx_mod_init
(
void
)
{
if
(
qd_probe
(
0x30
))
qd_probe
(
0xb0
);
if
(
ide_hwifs
[
0
].
chipset
!=
ide_qd65xx
&&
ide_hwifs
[
1
].
chipset
!=
ide_qd65xx
)
return
-
ENODEV
;
return
0
;
}
module_init
(
qd65xx_mod_init
);
void
__init
qd65xx_mod_exit
(
void
)
{
qd_unsetup
(
0
);
qd_unsetup
(
1
);
}
module_exit
(
qd65xx_mod_exit
);
#endif
drivers/ide/legacy/umc8672.c
View file @
26af05ea
...
...
@@ -39,6 +39,8 @@
*/
#define REALLY_SLOW_IO
/* some systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
...
...
@@ -52,7 +54,13 @@
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_UMC8672_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif
/* CONFIG_BLK_DEV_UMC8672_MODULE */
/*
* Default speeds. These can be changed with "auto-tune" and/or hdparm.
...
...
@@ -62,11 +70,11 @@
#define UMC_DRIVE2 1
/* 11 = Fastest Speed */
#define UMC_DRIVE3 1
/* In case of crash reduce speed */
static
byte
current_speeds
[
4
]
=
{
UMC_DRIVE0
,
UMC_DRIVE1
,
UMC_DRIVE2
,
UMC_DRIVE3
};
static
const
byte
pio_to_umc
[
5
]
=
{
0
,
3
,
7
,
10
,
11
};
/* rough guesses */
static
u8
current_speeds
[
4
]
=
{
UMC_DRIVE0
,
UMC_DRIVE1
,
UMC_DRIVE2
,
UMC_DRIVE3
};
static
const
u8
pio_to_umc
[
5
]
=
{
0
,
3
,
7
,
10
,
11
};
/* rough guesses */
/* 0 1 2 3 4 5 6 7 8 9 10 11 */
static
const
byte
speedtab
[
3
][
12
]
=
{
static
const
u8
speedtab
[
3
][
12
]
=
{
{
0xf
,
0xb
,
0x2
,
0x2
,
0x2
,
0x1
,
0x1
,
0x1
,
0x1
,
0x1
,
0x1
,
0x1
},
{
0x3
,
0x2
,
0x2
,
0x2
,
0x2
,
0x2
,
0x1
,
0x1
,
0x1
,
0x1
,
0x1
,
0x1
},
{
0xff
,
0xcb
,
0xc0
,
0x58
,
0x36
,
0x33
,
0x23
,
0x22
,
0x21
,
0x11
,
0x10
,
0x0
}};
...
...
@@ -77,13 +85,13 @@ static void out_umc (char port,char wert)
outb_p
(
wert
,
0x109
);
}
static
inline
byte
in_umc
(
char
port
)
static
inline
u8
in_umc
(
char
port
)
{
outb_p
(
port
,
0x108
);
return
inb_p
(
0x109
);
}
static
void
umc_set_speeds
(
byte
speeds
[])
static
void
umc_set_speeds
(
u8
speeds
[])
{
int
i
,
tmp
;
...
...
@@ -106,7 +114,7 @@ static void umc_set_speeds (byte speeds[])
speeds
[
0
],
speeds
[
1
],
speeds
[
2
],
speeds
[
3
]);
}
static
void
tune_umc
(
ide_drive_t
*
drive
,
byte
pio
)
static
void
tune_umc
(
ide_drive_t
*
drive
,
u8
pio
)
{
unsigned
long
flags
;
ide_hwgroup_t
*
hwgroup
=
ide_hwifs
[
HWIF
(
drive
)
->
index
^
1
].
hwgroup
;
...
...
@@ -116,7 +124,7 @@ static void tune_umc (ide_drive_t *drive, byte pio)
drive
->
name
,
pio
,
pio_to_umc
[
pio
]);
spin_lock_irqsave
(
&
ide_lock
,
flags
);
if
(
hwgroup
&&
hwgroup
->
handler
!=
NULL
)
{
printk
(
"umc8672: other interface is busy: exiting tune_umc()
\n
"
);
printk
(
KERN_ERR
"umc8672: other interface is busy: exiting tune_umc()
\n
"
);
}
else
{
current_speeds
[
drive
->
name
[
2
]
-
'a'
]
=
pio_to_umc
[
pio
];
umc_set_speeds
(
current_speeds
);
...
...
@@ -124,21 +132,21 @@ static void tune_umc (ide_drive_t *drive, byte pio)
spin_unlock_irqrestore
(
&
ide_lock
,
flags
);
}
void
__init
init_umc8672
(
void
)
/* called from ide.c */
int
__init
probe_umc8672
(
void
)
{
unsigned
long
flags
;
local_irq_save
(
flags
);
if
(
check_region
(
0x108
,
2
))
{
local_irq_restore
(
flags
);
printk
(
"
\n
umc8672: PORTS 0x108-0x109 ALREADY IN USE
\n
"
);
return
;
printk
(
KERN_ERR
"umc8672: ports 0x108-0x109 already in use.
\n
"
);
return
1
;
}
outb_p
(
0x5A
,
0x108
);
/* enable umc */
if
(
in_umc
(
0xd5
)
!=
0xa0
)
{
local_irq_restore
(
flags
);
printk
(
"umc8672: not found
\n
"
);
return
;
printk
(
KERN_ERR
"umc8672: not found
\n
"
);
return
1
;
}
outb_p
(
0xa5
,
0x108
);
/* disable umc */
...
...
@@ -153,4 +161,77 @@ void __init init_umc8672 (void) /* called from ide.c */
ide_hwifs
[
0
].
mate
=
&
ide_hwifs
[
1
];
ide_hwifs
[
1
].
mate
=
&
ide_hwifs
[
0
];
ide_hwifs
[
1
].
channel
=
1
;
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init
(
&
ide_hwifs
[
0
]);
probe_hwif_init
(
&
ide_hwifs
[
1
]);
#endif
/* HWIF_PROBE_CLASSIC_METHOD */
return
0
;
}
void
__init
umc8672_release
(
void
)
{
unsigned
long
flags
;
local_irq_save
(
flags
);
if
(
ide_hwifs
[
0
].
chipset
!=
ide_umc8672
&&
ide_hwifs
[
1
].
chipset
!=
ide_umc8672
)
{
local_irq_restore
(
flags
);
return
;
}
ide_hwifs
[
0
].
chipset
=
ide_unknown
;
ide_hwifs
[
1
].
chipset
=
ide_unknown
;
ide_hwifs
[
0
].
tuneproc
=
NULL
;
ide_hwifs
[
1
].
tuneproc
=
NULL
;
ide_hwifs
[
0
].
mate
=
NULL
;
ide_hwifs
[
1
].
mate
=
NULL
;
ide_hwifs
[
0
].
channel
=
0
;
ide_hwifs
[
1
].
channel
=
0
;
outb_p
(
0xa5
,
0x108
);
/* disable umc */
release_region
(
0x108
,
2
);
local_irq_restore
(
flags
);
}
#ifndef MODULE
/*
* init_umc8672:
*
* called by ide.c when parsing command line
*/
void
__init
init_umc8672
(
void
)
{
if
(
probe_umc8672
())
printk
(
KERN_ERR
"init_umc8672: umc8672 controller not found.
\n
"
);
}
#else
MODULE_AUTHOR
(
"Wolfram Podien"
);
MODULE_DESCRIPTION
(
"Support for UMC 8672 IDE chipset"
);
MODULE_LICENSE
(
"GPL"
);
int
__init
umc8672_mod_init
(
void
)
{
if
(
probe_umc8672
())
return
-
ENODEV
;
if
(
ide_hwifs
[
0
].
chipset
!=
ide_umc8672
&&
ide_hwifs
[
1
].
chipset
!=
ide_umc8672
)
{
umc8672_release
();
return
-
ENODEV
;
}
return
0
;
}
module_init
(
umc8672_mod_init
);
void
__init
umc8672_mod_exit
(
void
)
{
umc8672_release
();
}
module_exit
(
umc8672_mod_exit
);
#endif
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