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
581d2988
Commit
581d2988
authored
Nov 25, 2002
by
Alan Cox
Committed by
Linus Torvalds
Nov 25, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] driver for National SCx200 IDE
parent
88abbbb6
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
647 additions
and
0 deletions
+647
-0
drivers/ide/pci/sc1200.c
drivers/ide/pci/sc1200.c
+593
-0
drivers/ide/pci/sc1200.h
drivers/ide/pci/sc1200.h
+54
-0
No files found.
drivers/ide/pci/sc1200.c
0 → 100644
View file @
581d2988
/*
* linux/drivers/ide/sc1200.c Version 0.9 24-Oct-2002
*
* Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com>
* May be copied or modified under the terms of the GNU General Public License
*
* Development of this chipset driver was funded
* by the nice folks at National Semiconductor.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <linux/pm.h>
#include <asm/io.h>
#include <asm/irq.h>
#include "ide_modes.h"
#include "sc1200.h"
#define DISPLAY_SC1200_TIMINGS
#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
#include <linux/proc_fs.h>
static
int
sc1200_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
(
*
sc1200_display_info
)(
char
*
,
char
**
,
off_t
,
int
);
/* ide-proc.c */
extern
char
*
ide_media_verbose
(
ide_drive_t
*
);
static
u8
sc1200_proc
=
0
;
#define SC1200_REV_A 0x00
#define SC1200_REV_B1 0x01
#define SC1200_REV_B3 0x02
#define SC1200_REV_C1 0x03
#define SC1200_REV_D1 0x04
#define PCI_CLK_33 0x00
#define PCI_CLK_48 0x01
#define PCI_CLK_66 0x02
#define PCI_CLK_33A 0x03
static
unsigned
short
sc1200_get_pci_clock
(
void
)
{
unsigned
char
chip_id
,
silicon_revision
;
unsigned
int
pci_clock
;
/*
* Check the silicon revision, as not all versions of the chip
* have the register with the fast PCI bus timings.
*/
chip_id
=
inb
(
0x903c
);
silicon_revision
=
inb
(
0x903d
);
// Read the fast pci clock frequency
if
(
chip_id
==
0x04
&&
silicon_revision
<
SC1200_REV_B1
)
{
pci_clock
=
PCI_CLK_33
;
}
else
{
// check clock generator configuration (cfcc)
// the clock is in bits 8 and 9 of this word
pci_clock
=
inw
(
0x901e
);
pci_clock
>>=
8
;
pci_clock
&=
0x03
;
if
(
pci_clock
==
PCI_CLK_33A
)
pci_clock
=
PCI_CLK_33
;
}
return
pci_clock
;
}
static
struct
pci_dev
*
bmide_dev
;
static
int
sc1200_get_info
(
char
*
buffer
,
char
**
addr
,
off_t
offset
,
int
count
)
{
char
*
p
=
buffer
;
u32
bibma
=
pci_resource_start
(
bmide_dev
,
4
);
u8
c0
=
0
,
c1
=
0
;
/*
* at that point bibma+0x2 et bibma+0xa are byte registers
* to investigate:
*/
c0
=
inb_p
((
unsigned
short
)
bibma
+
0x02
);
c1
=
inb_p
((
unsigned
short
)
bibma
+
0x0a
);
p
+=
sprintf
(
p
,
"
\n
National SCx200 Chipset.
\n
"
);
p
+=
sprintf
(
p
,
"--------------- Primary Channel ---------------- Secondary Channel -------------
\n
"
);
p
+=
sprintf
(
p
,
" %sabled %sabled
\n
"
,
(
c0
&
0x80
)
?
"dis"
:
" en"
,
(
c1
&
0x80
)
?
"dis"
:
" en"
);
p
+=
sprintf
(
p
,
"--------------- drive0 --------- drive1 -------- 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 "
);
p
+=
sprintf
(
p
,
"UDMA
\n
"
);
p
+=
sprintf
(
p
,
"DMA
\n
"
);
p
+=
sprintf
(
p
,
"PIO
\n
"
);
return
p
-
buffer
;
}
#endif
/* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
extern
char
*
ide_xfer_verbose
(
byte
xfer_rate
);
/*
* Set a new transfer mode at the drive
*/
int
sc1200_set_xfer_mode
(
ide_drive_t
*
drive
,
byte
mode
)
{
printk
(
"%s: sc1200_set_xfer_mode(%s)
\n
"
,
drive
->
name
,
ide_xfer_verbose
(
mode
));
return
ide_config_drive_speed
(
drive
,
mode
);
}
/*
* Here are the standard PIO mode 0-4 timings for each "format".
* 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
const
unsigned
int
sc1200_pio_timings
[
4
][
5
]
=
{{
0x00009172
,
0x00012171
,
0x00020080
,
0x00032010
,
0x00040010
},
// format0 33Mhz
{
0xd1329172
,
0x71212171
,
0x30200080
,
0x20102010
,
0x00100010
},
// format1, 33Mhz
{
0xfaa3f4f3
,
0xc23232b2
,
0x513101c1
,
0x31213121
,
0x10211021
},
// format1, 48Mhz
{
0xfff4fff4
,
0xf35353d3
,
0x814102f1
,
0x42314231
,
0x11311131
}};
// format1, 66Mhz
/*
* After chip reset, the PIO timings are set to 0x00009172, which is not valid.
*/
//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172)
static
int
sc1200_autoselect_dma_mode
(
ide_drive_t
*
drive
)
{
int
udma_ok
=
1
,
mode
=
0
;
ide_hwif_t
*
hwif
=
HWIF
(
drive
);
int
unit
=
drive
->
select
.
b
.
unit
;
ide_drive_t
*
mate
=
&
hwif
->
drives
[
unit
^
1
];
struct
hd_driveid
*
id
=
drive
->
id
;
/*
* The SC1200 specifies that two drives sharing a cable cannot
* mix UDMA/MDMA. It has to be one or the other, for the pair,
* though different timings can still be chosen for each drive.
* We could set the appropriate timing bits on the fly,
* 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.
*/
if
(
mate
->
present
)
{
struct
hd_driveid
*
mateid
=
mate
->
id
;
if
(
mateid
&&
(
mateid
->
capability
&
1
)
&&
!
hwif
->
ide_dma_bad_drive
(
mate
))
{
if
((
mateid
->
field_valid
&
4
)
&&
(
mateid
->
dma_ultra
&
7
))
udma_ok
=
1
;
else
if
((
mateid
->
field_valid
&
2
)
&&
(
mateid
->
dma_mword
&
7
))
udma_ok
=
0
;
else
udma_ok
=
1
;
}
}
/*
* 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
->
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
;
else
if
(
id
->
dma_ultra
&
2
)
mode
=
XFER_UDMA_1
;
else
if
(
id
->
dma_ultra
&
1
)
mode
=
XFER_UDMA_0
;
}
if
(
!
mode
&&
(
id
->
field_valid
&
2
)
&&
(
id
->
dma_mword
&
7
))
{
if
(
id
->
dma_mword
&
4
)
mode
=
XFER_MW_DMA_2
;
else
if
(
id
->
dma_mword
&
2
)
mode
=
XFER_MW_DMA_1
;
else
if
(
id
->
dma_mword
&
1
)
mode
=
XFER_MW_DMA_0
;
}
}
return
mode
;
}
/*
* sc1200_config_dma2() handles selection/setting of DMA/UDMA modes
* for both the chipset and drive.
*/
static
int
sc1200_config_dma2
(
ide_drive_t
*
drive
,
int
mode
)
{
ide_hwif_t
*
hwif
=
HWIF
(
drive
);
int
unit
=
drive
->
select
.
b
.
unit
;
unsigned
int
reg
,
timings
;
unsigned
short
pci_clock
;
unsigned
int
basereg
=
hwif
->
channel
?
0x50
:
0x40
;
/*
* Default to DMA-off in case we run into trouble here.
*/
hwif
->
ide_dma_off_quietly
(
drive
);
/* turn off DMA while we fiddle */
outb
(
inb
(
hwif
->
dma_base
+
2
)
&~
(
unit
?
0x40
:
0x20
),
hwif
->
dma_base
+
2
);
/* clear DMA_capable bit */
/*
* Tell the drive to switch to the new mode; abort on failure.
*/
if
(
!
mode
||
sc1200_set_xfer_mode
(
drive
,
mode
))
{
printk
(
"SC1200: set xfer mode failure
\n
"
);
return
1
;
/* failure */
}
pci_clock
=
sc1200_get_pci_clock
();
/*
* Now tune the chipset to match the drive:
*
* Note that each DMA mode has several timings associated with it.
* The correct timing depends on the fast PCI clock freq.
*/
timings
=
0
;
switch
(
mode
)
{
case
XFER_UDMA_0
:
switch
(
pci_clock
)
{
case
PCI_CLK_33
:
timings
=
0x00921250
;
break
;
case
PCI_CLK_48
:
timings
=
0x00932470
;
break
;
case
PCI_CLK_66
:
timings
=
0x009436a1
;
break
;
}
break
;
case
XFER_UDMA_1
:
switch
(
pci_clock
)
{
case
PCI_CLK_33
:
timings
=
0x00911140
;
break
;
case
PCI_CLK_48
:
timings
=
0x00922260
;
break
;
case
PCI_CLK_66
:
timings
=
0x00933481
;
break
;
}
break
;
case
XFER_UDMA_2
:
switch
(
pci_clock
)
{
case
PCI_CLK_33
:
timings
=
0x00911030
;
break
;
case
PCI_CLK_48
:
timings
=
0x00922140
;
break
;
case
PCI_CLK_66
:
timings
=
0x00923261
;
break
;
}
break
;
case
XFER_MW_DMA_0
:
switch
(
pci_clock
)
{
case
PCI_CLK_33
:
timings
=
0x00077771
;
break
;
case
PCI_CLK_48
:
timings
=
0x000bbbb2
;
break
;
case
PCI_CLK_66
:
timings
=
0x000ffff3
;
break
;
}
break
;
case
XFER_MW_DMA_1
:
switch
(
pci_clock
)
{
case
PCI_CLK_33
:
timings
=
0x00012121
;
break
;
case
PCI_CLK_48
:
timings
=
0x00024241
;
break
;
case
PCI_CLK_66
:
timings
=
0x00035352
;
break
;
}
break
;
case
XFER_MW_DMA_2
:
switch
(
pci_clock
)
{
case
PCI_CLK_33
:
timings
=
0x00002020
;
break
;
case
PCI_CLK_48
:
timings
=
0x00013131
;
break
;
case
PCI_CLK_66
:
timings
=
0x00015151
;
break
;
}
break
;
}
if
(
timings
==
0
)
{
printk
(
"%s: sc1200_config_dma: huh? mode=%02x clk=%x
\n
"
,
drive
->
name
,
mode
,
pci_clock
);
return
1
;
/* failure */
}
if
(
unit
==
0
)
{
/* are we configuring drive0? */
pci_read_config_dword
(
hwif
->
pci_dev
,
basereg
+
4
,
&
reg
);
timings
|=
reg
&
0x80000000
;
/* preserve PIO format bit */
pci_write_config_dword
(
hwif
->
pci_dev
,
basereg
+
4
,
timings
);
}
else
{
pci_write_config_dword
(
hwif
->
pci_dev
,
basereg
+
12
,
timings
);
}
outb
(
inb
(
hwif
->
dma_base
+
2
)
|
(
unit
?
0x40
:
0x20
),
hwif
->
dma_base
+
2
);
/* set DMA_capable bit */
/*
* Finally, turn DMA on in software, and exit.
*/
return
hwif
->
ide_dma_on
(
drive
);
/* success */
}
/*
* sc1200_config_dma() handles selection/setting of DMA/UDMA modes
* for both the chipset and drive.
*/
static
int
sc1200_config_dma
(
ide_drive_t
*
drive
)
{
return
sc1200_config_dma2
(
drive
,
sc1200_autoselect_dma_mode
(
drive
));
}
/* Replacement for the standard ide_dma_end action in
* dma_proc.
*
* returns 1 on error, 0 otherwise
*/
int
sc1200_ide_dma_end
(
ide_drive_t
*
drive
)
{
ide_hwif_t
*
hwif
=
HWIF
(
drive
);
unsigned
long
dma_base
=
hwif
->
dma_base
;
byte
dma_stat
;
dma_stat
=
inb
(
dma_base
+
2
);
/* get DMA status */
if
(
!
(
dma_stat
&
4
))
printk
(
" ide_dma_end dma_stat=%0x err=%x newerr=%x
\n
"
,
dma_stat
,
((
dma_stat
&
7
)
!=
4
),
((
dma_stat
&
2
)
==
2
));
outb
(
dma_stat
|
0x1b
,
dma_base
+
2
);
/* clear the INTR & ERROR bits */
outb
(
inb
(
dma_base
)
&~
1
,
dma_base
);
/* !! DO THIS HERE !! stop DMA */
drive
->
waiting_for_dma
=
0
;
ide_destroy_dmatable
(
drive
);
/* purge DMA mappings */
return
(
dma_stat
&
7
)
!=
4
;
/* verify good DMA status */
}
/*
* sc1200_tuneproc() handles selection/setting of PIO modes
* for both the chipset and drive.
*
* All existing BIOSs for this chipset guarantee that all drives
* will have valid default PIO timings set up before we get here.
*/
static
void
sc1200_tuneproc
(
ide_drive_t
*
drive
,
byte
pio
)
/* mode=255 means "autotune" */
{
ide_hwif_t
*
hwif
=
HWIF
(
drive
);
unsigned
int
format
;
static
byte
modes
[
5
]
=
{
XFER_PIO_0
,
XFER_PIO_1
,
XFER_PIO_2
,
XFER_PIO_3
,
XFER_PIO_4
};
int
mode
=
-
1
;
switch
(
pio
)
{
case
200
:
mode
=
XFER_UDMA_0
;
break
;
case
201
:
mode
=
XFER_UDMA_1
;
break
;
case
202
:
mode
=
XFER_UDMA_2
;
break
;
case
100
:
mode
=
XFER_MW_DMA_0
;
break
;
case
101
:
mode
=
XFER_MW_DMA_1
;
break
;
case
102
:
mode
=
XFER_MW_DMA_2
;
break
;
}
if
(
mode
!=
-
1
)
{
printk
(
"SC1200: %s: changing (U)DMA mode
\n
"
,
drive
->
name
);
(
void
)
sc1200_config_dma2
(
drive
,
mode
);
return
;
}
pio
=
ide_get_best_pio_mode
(
drive
,
pio
,
4
,
NULL
);
printk
(
"SC1200: %s: setting PIO mode%d
\n
"
,
drive
->
name
,
pio
);
if
(
!
sc1200_set_xfer_mode
(
drive
,
modes
[
pio
]))
{
unsigned
int
basereg
=
hwif
->
channel
?
0x50
:
0x40
;
pci_read_config_dword
(
hwif
->
pci_dev
,
basereg
+
4
,
&
format
);
format
=
(
format
>>
31
)
&
1
;
if
(
format
)
format
+=
sc1200_get_pci_clock
();
pci_write_config_dword
(
hwif
->
pci_dev
,
basereg
+
(
drive
->
select
.
b
.
unit
<<
3
),
sc1200_pio_timings
[
format
][
pio
]);
}
}
static
ide_hwif_t
*
lookup_pci_dev
(
ide_hwif_t
*
prev
,
struct
pci_dev
*
dev
)
{
int
h
;
for
(
h
=
0
;
h
<
MAX_HWIFS
;
h
++
)
{
ide_hwif_t
*
hwif
=
&
ide_hwifs
[
h
];
if
(
prev
)
{
if
(
hwif
==
prev
)
prev
=
NULL
;
// found previous, now look for next match
}
else
{
if
(
hwif
&&
hwif
->
pci_dev
==
dev
)
return
hwif
;
// found next match
}
}
return
NULL
;
// not found
}
typedef
struct
sc1200_saved_state_s
{
__u32
regs
[
4
];
}
sc1200_saved_state_t
;
static
int
sc1200_save_state
(
struct
pci_dev
*
dev
,
u32
state
)
{
ide_hwif_t
*
hwif
=
NULL
;
printk
(
"SC1200: save_state(%u)
\n
"
,
state
);
if
(
state
!=
0
)
return
0
;
// we only save state when going from full power to less
//
// Loop over all interfaces that are part of this PCI device:
//
while
((
hwif
=
lookup_pci_dev
(
hwif
,
dev
))
!=
NULL
)
{
sc1200_saved_state_t
*
ss
;
unsigned
int
basereg
,
r
;
//
// allocate a permanent save area, if not already allocated
//
ss
=
(
sc1200_saved_state_t
*
)
hwif
->
config_data
;
if
(
ss
==
NULL
)
{
ss
=
kmalloc
(
sizeof
(
sc1200_saved_state_t
),
GFP_KERNEL
);
if
(
ss
==
NULL
)
return
-
ENOMEM
;
(
sc1200_saved_state_t
*
)
hwif
->
config_data
=
ss
;
}
ss
=
(
sc1200_saved_state_t
*
)
hwif
->
config_data
;
//
// Save timing registers: this may be unnecessary if BIOS also does it
//
basereg
=
hwif
->
channel
?
0x50
:
0x40
;
for
(
r
=
0
;
r
<
4
;
++
r
)
{
pci_read_config_dword
(
hwif
->
pci_dev
,
basereg
+
(
r
<<
2
),
&
ss
->
regs
[
r
]);
}
}
return
0
;
}
static
int
sc1200_suspend
(
struct
pci_dev
*
dev
,
u32
state
)
{
ide_hwif_t
*
hwif
=
NULL
;
printk
(
"SC1200: suspend(%u)
\n
"
,
state
);
/* You don't need to iterate over disks -- sysfs should have done that for you already */
pci_disable_device
(
dev
);
pci_set_power_state
(
dev
,
state
);
dev
->
current_state
=
state
;
return
0
;
}
static
int
sc1200_resume
(
struct
pci_dev
*
dev
)
{
ide_hwif_t
*
hwif
=
NULL
;
printk
(
"SC1200: resume
\n
"
);
pci_set_power_state
(
dev
,
0
);
// bring chip back from sleep state
dev
->
current_state
=
0
;
pci_enable_device
(
dev
);
//
// loop over all interfaces that are part of this pci device:
//
while
((
hwif
=
lookup_pci_dev
(
hwif
,
dev
))
!=
NULL
)
{
unsigned
int
basereg
,
r
,
d
,
format
;
sc1200_saved_state_t
*
ss
=
(
sc1200_saved_state_t
*
)
hwif
->
config_data
;
printk
(
"%s: SC1200: resume
\n
"
,
hwif
->
name
);
//
// Restore timing registers: this may be unnecessary if BIOS also does it
//
basereg
=
hwif
->
channel
?
0x50
:
0x40
;
if
(
ss
!=
NULL
)
{
for
(
r
=
0
;
r
<
4
;
++
r
)
{
pci_write_config_dword
(
hwif
->
pci_dev
,
basereg
+
(
r
<<
2
),
ss
->
regs
[
r
]);
}
}
//
// Re-program drive PIO modes
//
pci_read_config_dword
(
hwif
->
pci_dev
,
basereg
+
4
,
&
format
);
format
=
(
format
>>
31
)
&
1
;
if
(
format
)
format
+=
sc1200_get_pci_clock
();
for
(
d
=
0
;
d
<
2
;
++
d
)
{
ide_drive_t
*
drive
=
&
(
hwif
->
drives
[
d
]);
if
(
drive
->
present
)
{
unsigned
int
pio
,
timings
;
pci_read_config_dword
(
hwif
->
pci_dev
,
basereg
+
(
drive
->
select
.
b
.
unit
<<
3
),
&
timings
);
for
(
pio
=
0
;
pio
<=
4
;
++
pio
)
{
if
(
sc1200_pio_timings
[
format
][
pio
]
==
timings
)
break
;
}
if
(
pio
>
4
)
pio
=
255
;
/* autotune */
(
void
)
sc1200_tuneproc
(
drive
,
pio
);
}
}
//
// Re-program drive DMA modes
//
for
(
d
=
0
;
d
<
MAX_DRIVES
;
++
d
)
{
ide_drive_t
*
drive
=
&
(
hwif
->
drives
[
d
]);
if
(
drive
->
present
&&
!
hwif
->
ide_dma_bad_drive
(
drive
))
{
int
was_using_dma
=
drive
->
using_dma
;
hwif
->
ide_dma_off_quietly
(
drive
);
sc1200_config_dma
(
drive
);
if
(
!
was_using_dma
&&
drive
->
using_dma
)
{
hwif
->
ide_dma_off_quietly
(
drive
);
}
}
}
}
return
0
;
}
/*
* Initialize the sc1200 bridge for reliable IDE DMA operation.
*/
static
unsigned
int
__init
init_chipset_sc1200
(
struct
pci_dev
*
dev
,
const
char
*
name
)
{
#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
if
(
!
bmide_dev
)
{
sc1200_proc
=
1
;
bmide_dev
=
dev
;
ide_pci_register_host_proc
(
&
sc1200_procs
[
0
]);
}
#endif
/* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
return
0
;
}
/*
* This gets invoked by the IDE driver once for each channel,
* and performs channel-specific pre-initialization before drive probing.
*/
static
void
__init
init_hwif_sc1200
(
ide_hwif_t
*
hwif
)
{
if
(
hwif
->
mate
)
hwif
->
serialized
=
hwif
->
mate
->
serialized
=
1
;
hwif
->
autodma
=
0
;
if
(
hwif
->
dma_base
)
{
hwif
->
ide_dma_check
=
&
sc1200_config_dma
;
hwif
->
ide_dma_end
=
&
sc1200_ide_dma_end
;
if
(
!
noautodma
)
hwif
->
autodma
=
1
;
hwif
->
tuneproc
=
&
sc1200_tuneproc
;
}
hwif
->
atapi_dma
=
1
;
hwif
->
ultra_mask
=
0x07
;
hwif
->
mwdma_mask
=
0x07
;
hwif
->
drives
[
0
].
autodma
=
hwif
->
autodma
;
hwif
->
drives
[
1
].
autodma
=
hwif
->
autodma
;
}
static
void
__init
init_dma_sc1200
(
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
*
);
static
int
__devinit
sc1200_init_one
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
id
)
{
ide_pci_device_t
*
d
=
&
sc1200_chipsets
[
id
->
driver_data
];
if
(
dev
->
device
!=
d
->
device
)
BUG
();
ide_setup_pci_device
(
dev
,
d
);
MOD_INC_USE_COUNT
;
return
0
;
}
static
struct
pci_device_id
sc1200_pci_tbl
[]
__devinitdata
=
{
{
PCI_VENDOR_ID_NS
,
PCI_DEVICE_ID_NS_SCx200_IDE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
0
,
},
};
static
struct
pci_driver
driver
=
{
.
name
=
"SC1200 IDE"
,
.
id_table
=
sc1200_pci_tbl
,
.
probe
=
sc1200_init_one
,
.
save_state
=
sc1200_save_state
,
.
suspend
=
sc1200_suspend
,
.
resume
=
sc1200_resume
,
};
static
int
sc1200_ide_init
(
void
)
{
return
ide_pci_register_driver
(
&
driver
);
}
static
void
sc1200_ide_exit
(
void
)
{
ide_pci_unregister_driver
(
&
driver
);
}
module_init
(
sc1200_ide_init
);
module_exit
(
sc1200_ide_exit
);
MODULE_AUTHOR
(
"Mark Lord"
);
MODULE_DESCRIPTION
(
"PCI driver module for NS SC1200 IDE"
);
MODULE_LICENSE
(
"GPL"
);
EXPORT_NO_SYMBOLS
;
drivers/ide/pci/sc1200.h
0 → 100644
View file @
581d2988
#ifndef SC1200_H
#define SC1200_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_SC1200_TIMINGS
#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
#include <linux/proc_fs.h>
static
u8
sc1200_proc
;
static
int
sc1200_get_info
(
char
*
,
char
**
,
off_t
,
int
);
static
ide_pci_host_proc_t
sc1200_procs
[]
__initdata
=
{
{
name:
"sc1200"
,
set:
1
,
get_info:
sc1200_get_info
,
parent:
NULL
,
},
};
#endif
/* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
static
unsigned
int
init_chipset_sc1200
(
struct
pci_dev
*
,
const
char
*
);
static
void
init_hwif_sc1200
(
ide_hwif_t
*
);
static
void
init_dma_sc1200
(
ide_hwif_t
*
,
unsigned
long
);
static
ide_pci_device_t
sc1200_chipsets
[]
__devinitdata
=
{
{
/* 0 */
vendor:
PCI_VENDOR_ID_NS
,
device:
PCI_DEVICE_ID_NS_SCx200_IDE
,
name:
"SC1200"
,
init_chipset:
init_chipset_sc1200
,
init_iops:
NULL
,
init_hwif:
init_hwif_sc1200
,
init_dma:
init_dma_sc1200
,
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
/* SC1200_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