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
43acf7e0
Commit
43acf7e0
authored
May 12, 2003
by
Dave Jones
Browse files
Options
Browse Files
Download
Plain Diff
Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus
into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart
parents
5f2d71d6
55e174df
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
257 additions
and
214 deletions
+257
-214
drivers/char/agp/Makefile
drivers/char/agp/Makefile
+1
-1
drivers/char/agp/agp.h
drivers/char/agp/agp.h
+16
-3
drivers/char/agp/amd-k8-agp.c
drivers/char/agp/amd-k8-agp.c
+30
-4
drivers/char/agp/generic.c
drivers/char/agp/generic.c
+132
-59
drivers/char/agp/isoch.c
drivers/char/agp/isoch.c
+78
-147
No files found.
drivers/char/agp/Makefile
View file @
43acf7e0
agpgart-y
:=
backend.o frontend.o generic.o
generic-3.0
.o
agpgart-y
:=
backend.o frontend.o generic.o
isoch
.o
obj-$(CONFIG_AGP)
+=
agpgart.o
obj-$(CONFIG_AGP)
+=
agpgart.o
obj-$(CONFIG_AGP_ALI)
+=
ali-agp.o
obj-$(CONFIG_AGP_ALI)
+=
ali-agp.o
...
...
drivers/char/agp/agp.h
View file @
43acf7e0
...
@@ -139,6 +139,8 @@ struct agp_bridge_data {
...
@@ -139,6 +139,8 @@ struct agp_bridge_data {
int
max_memory_agp
;
/* in number of pages */
int
max_memory_agp
;
/* in number of pages */
int
aperture_size_idx
;
int
aperture_size_idx
;
int
capndx
;
int
capndx
;
char
major_version
;
char
minor_version
;
};
};
#define OUTREG64(mmap, addr, val) __raw_writeq((val), (mmap)+(addr))
#define OUTREG64(mmap, addr, val) __raw_writeq((val), (mmap)+(addr))
...
@@ -388,27 +390,38 @@ void agp_free_key(int key);
...
@@ -388,27 +390,38 @@ void agp_free_key(int key);
int
agp_num_entries
(
void
);
int
agp_num_entries
(
void
);
u32
agp_collect_device_status
(
u32
mode
,
u32
command
);
u32
agp_collect_device_status
(
u32
mode
,
u32
command
);
void
agp_device_command
(
u32
command
,
int
agp_v3
);
void
agp_device_command
(
u32
command
,
int
agp_v3
);
int
agp_3_0_node_enable
(
struct
agp_bridge_data
*
bridge
,
u32
mode
,
u32
minor
);
int
agp_3_0_enable
(
struct
agp_bridge_data
*
bridge
,
u32
mode
);
int
agp_3_5_enable
(
struct
agp_bridge_data
*
bridge
,
u32
mode
);
void
global_cache_flush
(
void
);
void
global_cache_flush
(
void
);
void
get_agp_version
(
struct
agp_bridge_data
*
bridge
);
/* Standard agp registers */
/* Standard agp registers */
#define AGPSTAT 0x4
#define AGPSTAT 0x4
#define AGPCMD 0x8
#define AGPCMD 0x8
#define AGPNISTAT 0xc
#define AGPNEPG 0x16
#define AGPNEPG 0x16
#define AGPNICMD 0x20
#define AGP_MAJOR_VERSION_SHIFT (20)
#define AGP_MAJOR_VERSION_SHIFT (20)
#define AGP_MINOR_VERSION_SHIFT (16)
#define AGP_MINOR_VERSION_SHIFT (16)
#define AGPSTAT_RQ_DEPTH (0xff000000)
#define AGPSTAT_RQ_DEPTH (0xff000000)
#define AGPSTAT_CAL_MASK (1<<12|1<<11|1<<10)
#define AGPSTAT_ARQSZ (1<<15|1<<14|1<<13)
#define AGPSTAT_ARQSZ_SHIFT 13
#define AGPSTAT_ARQSZ_SHIFT 13
#define AGPSTAT_AGP_ENABLE (1<<8)
#define AGPSTAT_SBA (1<<9)
#define AGPSTAT_SBA (1<<9)
#define AGPSTAT_AGP_ENABLE (1<<8)
#define AGPSTAT_FW (1<<4)
#define AGPSTAT_MODE_3_0 (1<<3)
#define AGPSTAT2_1X (1<<0)
#define AGPSTAT2_1X (1<<0)
#define AGPSTAT2_2X (1<<1)
#define AGPSTAT2_2X (1<<1)
#define AGPSTAT2_4X (1<<2)
#define AGPSTAT2_4X (1<<2)
#define AGPSTAT_FW (1<<4)
#define AGPSTAT3_RSVD (1<<2)
#define AGPSTAT3_8X (1<<1)
#define AGPSTAT3_4X (1)
#endif
/* _AGP_BACKEND_PRIV_H */
#endif
/* _AGP_BACKEND_PRIV_H */
drivers/char/agp/amd-k8-agp.c
View file @
43acf7e0
...
@@ -253,8 +253,10 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev,
...
@@ -253,8 +253,10 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev,
{
{
struct
agp_bridge_data
*
bridge
;
struct
agp_bridge_data
*
bridge
;
struct
pci_dev
*
loop_dev
;
struct
pci_dev
*
loop_dev
;
u8
rev_id
;
u8
cap_ptr
;
u8
cap_ptr
;
int
i
=
0
;
int
i
=
0
;
char
*
revstring
=
" "
;
cap_ptr
=
pci_find_capability
(
pdev
,
PCI_CAP_ID_AGP
);
cap_ptr
=
pci_find_capability
(
pdev
,
PCI_CAP_ID_AGP
);
if
(
!
cap_ptr
)
if
(
!
cap_ptr
)
...
@@ -266,14 +268,38 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev,
...
@@ -266,14 +268,38 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev,
if
(
!
bridge
)
if
(
!
bridge
)
return
-
ENOMEM
;
return
-
ENOMEM
;
/* Assume here we have an 8151. (Later this assumption will be fixed). */
pci_read_config_byte
(
pdev
,
PCI_REVISION_ID
,
&
rev_id
);
switch
(
rev_id
)
{
case
0x01
:
revstring
=
"A0"
;
break
;
case
0x02
:
revstring
=
"A1"
;
break
;
case
0x11
:
revstring
=
"B0"
;
break
;
case
0x12
:
revstring
=
"B1"
;
break
;
case
0x13
:
revstring
=
"B2"
;
break
;
default:
revstring
=
"??"
;
break
;
}
printk
(
"Detected AMD 8151 AGP Bridge rev %s"
,
revstring
);
/*
* Work around errata.
* Chips before B2 stepping incorrectly reporting v3.5
*/
if
(
rev_id
<
0x13
)
{
bridge
->
major_version
=
3
;
bridge
->
minor_version
=
0
;
}
bridge
->
driver
=
&
amd_8151_driver
;
bridge
->
driver
=
&
amd_8151_driver
;
bridge
->
dev
=
pdev
;
bridge
->
dev
=
pdev
;
bridge
->
capndx
=
cap_ptr
;
bridge
->
capndx
=
cap_ptr
;
/* Fill in the mode register */
/* Fill in the mode register */
pci_read_config_dword
(
pdev
,
pci_read_config_dword
(
pdev
,
bridge
->
capndx
+
PCI_AGP_STATUS
,
&
bridge
->
mode
);
bridge
->
capndx
+
PCI_AGP_STATUS
,
&
bridge
->
mode
);
/* cache pci_devs of northbridges. */
/* cache pci_devs of northbridges. */
pci_for_each_dev
(
loop_dev
)
{
pci_for_each_dev
(
loop_dev
)
{
...
@@ -290,7 +316,7 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev,
...
@@ -290,7 +316,7 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev,
pci_set_drvdata
(
pdev
,
bridge
);
pci_set_drvdata
(
pdev
,
bridge
);
return
agp_add_bridge
(
bridge
);
return
agp_add_bridge
(
bridge
);
out_free:
out_free:
agp_put_bridge
(
bridge
);
agp_put_bridge
(
bridge
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
...
...
drivers/char/agp/generic.c
View file @
43acf7e0
...
@@ -270,14 +270,16 @@ EXPORT_SYMBOL_GPL(agp_num_entries);
...
@@ -270,14 +270,16 @@ EXPORT_SYMBOL_GPL(agp_num_entries);
int
agp_copy_info
(
agp_kern_info
*
info
)
int
agp_copy_info
(
agp_kern_info
*
info
)
{
{
memset
(
info
,
0
,
sizeof
(
agp_kern_info
));
memset
(
info
,
0
,
sizeof
(
agp_kern_info
));
if
(
agp_bridge
->
type
==
NOT_SUPPORTED
)
{
if
(
!
agp_bridge
||
agp_bridge
->
type
==
NOT_SUPPORTED
||
info
->
chipset
=
agp_bridge
->
type
;
!
agp_bridge
->
version
)
{
info
->
chipset
=
NOT_SUPPORTED
;
return
-
EIO
;
return
-
EIO
;
}
}
info
->
version
.
major
=
agp_bridge
->
version
->
major
;
info
->
version
.
major
=
agp_bridge
->
version
->
major
;
info
->
version
.
minor
=
agp_bridge
->
version
->
minor
;
info
->
version
.
minor
=
agp_bridge
->
version
->
minor
;
info
->
device
=
agp_bridge
->
dev
;
info
->
chipset
=
agp_bridge
->
type
;
info
->
chipset
=
agp_bridge
->
type
;
info
->
device
=
agp_bridge
->
dev
;
info
->
mode
=
agp_bridge
->
mode
;
info
->
mode
=
agp_bridge
->
mode
;
info
->
aper_base
=
agp_bridge
->
gart_bus_addr
;
info
->
aper_base
=
agp_bridge
->
gart_bus_addr
;
info
->
aper_size
=
agp_return_size
();
info
->
aper_size
=
agp_return_size
();
...
@@ -366,60 +368,106 @@ EXPORT_SYMBOL(agp_unbind_memory);
...
@@ -366,60 +368,106 @@ EXPORT_SYMBOL(agp_unbind_memory);
/* Generic Agp routines - Start */
/* Generic Agp routines - Start */
static
void
agp_v2_parse_one
(
u32
*
mode
,
u32
*
cmd
,
u32
*
tmp
)
{
/* disable SBA if it's not supported */
if
(
!
((
*
cmd
&
AGPSTAT_SBA
)
&&
(
*
tmp
&
AGPSTAT_SBA
)
&&
(
*
mode
&
AGPSTAT_SBA
)))
*
cmd
&=
~
AGPSTAT_SBA
;
/* disable FW if it's not supported */
if
(
!
((
*
cmd
&
AGPSTAT_FW
)
&&
(
*
tmp
&
AGPSTAT_FW
)
&&
(
*
mode
&
AGPSTAT_FW
)))
*
cmd
&=
~
AGPSTAT_FW
;
/* Set speed */
if
(
!
((
*
cmd
&
AGPSTAT2_4X
)
&&
(
*
tmp
&
AGPSTAT2_4X
)
&&
(
*
mode
&
AGPSTAT2_4X
)))
*
cmd
&=
~
AGPSTAT2_4X
;
if
(
!
((
*
cmd
&
AGPSTAT2_2X
)
&&
(
*
tmp
&
AGPSTAT2_2X
)
&&
(
*
mode
&
AGPSTAT2_2X
)))
*
cmd
&=
~
AGPSTAT2_2X
;
if
(
!
((
*
cmd
&
AGPSTAT2_1X
)
&&
(
*
tmp
&
AGPSTAT2_1X
)
&&
(
*
mode
&
AGPSTAT2_1X
)))
*
cmd
&=
~
AGPSTAT2_1X
;
/* Now we know what mode it should be, clear out the unwanted bits. */
if
(
*
cmd
&
AGPSTAT2_4X
)
*
cmd
&=
~
(
AGPSTAT2_1X
|
AGPSTAT2_2X
);
/* 4X */
if
(
*
cmd
&
AGPSTAT2_2X
)
*
cmd
&=
~
(
AGPSTAT2_1X
|
AGPSTAT2_4X
);
/* 2X */
if
(
*
cmd
&
AGPSTAT2_1X
)
*
cmd
&=
~
(
AGPSTAT2_2X
|
AGPSTAT2_4X
);
/* 1Xf */
}
u32
agp_collect_device_status
(
u32
mode
,
u32
command
)
static
void
agp_v3_parse_one
(
u32
*
mode
,
u32
*
cmd
,
u32
*
tmp
)
{
/* ARQSZ - Set the value to the maximum one.
* Don't allow the mode register to override values. */
*
cmd
=
((
*
cmd
&
~
AGPSTAT_ARQSZ
)
|
max_t
(
u32
,(
*
cmd
&
AGPSTAT_ARQSZ
),(
*
tmp
&
AGPSTAT_ARQSZ
)));
/* Calibration cycle.
* Don't allow the mode register to override values. */
*
cmd
=
((
*
cmd
&
~
AGPSTAT_CAL_MASK
)
|
min_t
(
u32
,(
*
cmd
&
AGPSTAT_CAL_MASK
),(
*
tmp
&
AGPSTAT_CAL_MASK
)));
/* SBA *must* be supported for AGP v3 */
*
cmd
|=
AGPSTAT_SBA
;
/* disable FW if it's not supported */
if
(
!
((
*
cmd
&
AGPSTAT_FW
)
&&
(
*
tmp
&
AGPSTAT_FW
)
&&
(
*
mode
&
AGPSTAT_FW
)))
*
cmd
&=
~
AGPSTAT_FW
;
/* Set speed. */
if
(
!
((
*
cmd
&
AGPSTAT3_8X
)
&&
(
*
tmp
&
AGPSTAT3_8X
)
&&
(
*
mode
&
AGPSTAT3_8X
)))
*
cmd
&=
~
AGPSTAT3_8X
;
if
(
!
((
*
cmd
&
AGPSTAT3_4X
)
&&
(
*
tmp
&
AGPSTAT3_4X
)
&&
(
*
mode
&
AGPSTAT3_4X
)))
*
cmd
&=
~
AGPSTAT3_4X
;
/* Clear out unwanted bits. */
if
(
*
cmd
&
AGPSTAT3_8X
)
*
cmd
*=
~
(
AGPSTAT3_4X
|
AGPSTAT3_RSVD
);
if
(
*
cmd
&
AGPSTAT3_4X
)
*
cmd
*=
~
(
AGPSTAT3_8X
|
AGPSTAT3_RSVD
);
}
//FIXME: This doesn't smell right.
//We need a function we pass an agp_device to.
u32
agp_collect_device_status
(
u32
mode
,
u32
cmd
)
{
{
struct
pci_dev
*
device
;
struct
pci_dev
*
device
;
u8
agp
;
u8
cap_ptr
;
u32
scratch
;
u32
tmp
;
u32
agp3
;
pci_for_each_dev
(
device
)
{
pci_for_each_dev
(
device
)
{
agp
=
pci_find_capability
(
device
,
PCI_CAP_ID_AGP
);
cap_ptr
=
pci_find_capability
(
device
,
PCI_CAP_ID_AGP
);
if
(
!
agp
)
if
(
!
cap_ptr
)
continue
;
continue
;
/*
/*
* Ok, here we have a AGP device. Disable impossible
* Ok, here we have a AGP device. Disable impossible
* settings, and adjust the readqueue to the minimum.
* settings, and adjust the readqueue to the minimum.
*/
*/
pci_read_config_dword
(
device
,
agp
+
PCI_AGP_STATUS
,
&
scratch
);
pci_read_config_dword
(
device
,
cap_ptr
+
PCI_AGP_STATUS
,
&
tmp
);
/* adjust RQ depth */
/* adjust RQ depth */
c
ommand
=
((
comman
d
&
~
AGPSTAT_RQ_DEPTH
)
|
c
md
=
((
cm
d
&
~
AGPSTAT_RQ_DEPTH
)
|
min_t
(
u32
,
(
mode
&
AGPSTAT_RQ_DEPTH
),
min_t
(
u32
,
(
mode
&
AGPSTAT_RQ_DEPTH
),
min_t
(
u32
,
(
command
&
AGPSTAT_RQ_DEPTH
),
min_t
(
u32
,
(
cmd
&
AGPSTAT_RQ_DEPTH
),
(
tmp
&
AGPSTAT_RQ_DEPTH
))));
(
scratch
&
AGPSTAT_RQ_DEPTH
))));
pci_read_config_dword
(
device
,
cap_ptr
+
AGPSTAT
,
&
agp3
);
/* disable SBA if it's not supported */
if
(
!
((
command
&
AGPSTAT_SBA
)
&&
(
scratch
&
AGPSTAT_SBA
)
&&
(
mode
&
AGPSTAT_SBA
)))
command
&=
~
AGPSTAT_SBA
;
/* disable FW if it's not supported */
if
(
!
((
command
&
AGPSTAT_FW
)
&&
(
scratch
&
AGPSTAT_FW
)
&&
(
mode
&
AGPSTAT_FW
)))
command
&=
~
AGPSTAT_FW
;
/* Set speed */
if
(
!
((
command
&
AGPSTAT2_4X
)
&&
(
scratch
&
AGPSTAT2_4X
)
&&
(
mode
&
AGPSTAT2_4X
)))
command
&=
~
AGPSTAT2_4X
;
if
(
!
((
command
&
AGPSTAT2_2X
)
&&
(
scratch
&
AGPSTAT2_2X
)
&&
(
mode
&
AGPSTAT2_2X
)))
/* Check to see if we are operating in 3.0 mode */
command
&=
~
AGPSTAT2_2X
;
if
(
agp3
&
AGPSTAT_MODE_3_0
)
{
agp_v3_parse_one
(
&
mode
,
&
cmd
,
&
tmp
);
if
(
!
((
command
&
AGPSTAT2_1X
)
&&
(
scratch
&
AGPSTAT2_1X
)
&&
(
mode
&
AGPSTAT2_1X
)))
}
else
{
command
&=
~
AGPSTAT2_1X
;
agp_v2_parse_one
(
&
mode
,
&
cmd
,
&
tmp
);
}
}
}
return
cmd
;
/* Now we know what mode it should be, clear out the unwanted bits. */
if
(
command
&
AGPSTAT2_4X
)
command
&=
~
(
AGPSTAT2_1X
|
AGPSTAT2_2X
);
/* 4X */
if
(
command
&
AGPSTAT2_2X
)
command
&=
~
(
AGPSTAT2_1X
|
AGPSTAT2_4X
);
/* 2X */
if
(
command
&
AGPSTAT2_1X
)
command
&=
~
(
AGPSTAT2_2X
|
AGPSTAT2_4X
);
/* 1Xf */
return
command
;
}
}
EXPORT_SYMBOL
(
agp_collect_device_status
);
EXPORT_SYMBOL
(
agp_collect_device_status
);
...
@@ -446,29 +494,33 @@ void agp_device_command(u32 command, int agp_v3)
...
@@ -446,29 +494,33 @@ void agp_device_command(u32 command, int agp_v3)
EXPORT_SYMBOL
(
agp_device_command
);
EXPORT_SYMBOL
(
agp_device_command
);
void
agp_generic_enable
(
u32
mod
e
)
void
get_agp_version
(
struct
agp_bridge_data
*
bridg
e
)
{
{
u32
command
,
ncapid
,
major
,
minor
;
u32
ncapid
;
/* Exit early if already set by errata workarounds. */
if
(
agp_bridge
->
major_version
!=
0
)
return
;
pci_read_config_dword
(
agp_bridge
->
dev
,
agp_bridge
->
capndx
,
&
ncapid
);
pci_read_config_dword
(
agp_bridge
->
dev
,
agp_bridge
->
capndx
,
&
ncapid
);
major
=
(
ncapid
>>
20
)
&
0xf
;
agp_bridge
->
major_version
=
(
ncapid
>>
AGP_MAJOR_VERSION_SHIFT
)
&
0xf
;
minor
=
(
ncapid
>>
16
)
&
0xf
;
agp_bridge
->
minor_version
=
(
ncapid
>>
AGP_MINOR_VERSION_SHIFT
)
&
0xf
;
printk
(
KERN_INFO
PFX
"Found an AGP %d.%d compliant device.
\n
"
,
major
,
minor
);
}
EXPORT_SYMBOL
(
get_agp_version
);
if
(
major
>=
3
)
{
u32
agp_3_0
;
pci_read_config_dword
(
agp_bridge
->
dev
,
agp_bridge
->
capndx
+
0x4
,
&
agp_3_0
);
void
agp_generic_enable
(
u32
mode
)
/* Check to see if we are operating in 3.0 mode */
{
if
((
agp_3_0
>>
3
)
&
0x1
)
{
u32
command
;
agp_3_0_node_enable
(
agp_bridge
,
mode
,
minor
);
u32
agp3
;
return
;
}
else
{
get_agp_version
(
agp_bridge
);
printk
(
KERN_INFO
PFX
"not in AGP 3.0 mode, falling back to 2.x
\n
"
);
}
printk
(
KERN_INFO
PFX
"Found an AGP %d.%d compliant device at %s.
\n
"
,
}
agp_bridge
->
major_version
,
agp_bridge
->
minor_version
,
agp_bridge
->
dev
->
slot_name
);
/* AGP v<3 */
pci_read_config_dword
(
agp_bridge
->
dev
,
pci_read_config_dword
(
agp_bridge
->
dev
,
agp_bridge
->
capndx
+
PCI_AGP_STATUS
,
&
command
);
agp_bridge
->
capndx
+
PCI_AGP_STATUS
,
&
command
);
...
@@ -477,7 +529,27 @@ void agp_generic_enable(u32 mode)
...
@@ -477,7 +529,27 @@ void agp_generic_enable(u32 mode)
pci_write_config_dword
(
agp_bridge
->
dev
,
pci_write_config_dword
(
agp_bridge
->
dev
,
agp_bridge
->
capndx
+
PCI_AGP_COMMAND
,
command
);
agp_bridge
->
capndx
+
PCI_AGP_COMMAND
,
command
);
agp_device_command
(
command
,
0
);
/* Do AGP version specific frobbing. */
if
(
agp_bridge
->
major_version
>=
3
)
{
pci_read_config_dword
(
agp_bridge
->
dev
,
agp_bridge
->
capndx
+
AGPSTAT
,
&
agp3
);
/* Check to see if we are operating in 3.0 mode */
if
(
agp3
&
AGPSTAT_MODE_3_0
)
{
/* If we have 3.5, we can do the isoch stuff. */
if
(
agp_bridge
->
minor_version
>=
5
)
agp_3_5_enable
(
agp_bridge
,
mode
);
agp_device_command
(
command
,
TRUE
);
return
;
}
else
{
printk
(
KERN_INFO
PFX
"Device is in legacy mode,"
" falling back to 2.x
\n
"
);
}
}
/* AGP v<3 */
agp_device_command
(
command
,
FALSE
);
}
}
EXPORT_SYMBOL
(
agp_generic_enable
);
EXPORT_SYMBOL
(
agp_generic_enable
);
...
@@ -831,6 +903,7 @@ void agp_enable(u32 mode)
...
@@ -831,6 +903,7 @@ void agp_enable(u32 mode)
}
}
EXPORT_SYMBOL
(
agp_enable
);
EXPORT_SYMBOL
(
agp_enable
);
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
static
void
ipi_handler
(
void
*
null
)
static
void
ipi_handler
(
void
*
null
)
{
{
...
...
drivers/char/agp/
generic-3.0
.c
→
drivers/char/agp/
isoch
.c
View file @
43acf7e0
/*
/*
*
Generic routines for AGP 3.0
compliant bridges.
*
Setup routines for AGP 3.5
compliant bridges.
*/
*/
#include <linux/list.h>
#include <linux/list.h>
...
@@ -9,47 +9,47 @@
...
@@ -9,47 +9,47 @@
#include "agp.h"
#include "agp.h"
/* Generic AGP 3.
0
enabling routines */
/* Generic AGP 3.
5
enabling routines */
struct
agp_3_
0
_dev
{
struct
agp_3_
5
_dev
{
struct
list_head
list
;
struct
list_head
list
;
u8
capndx
;
u8
capndx
;
u32
maxbw
;
u32
maxbw
;
struct
pci_dev
*
dev
;
struct
pci_dev
*
dev
;
};
};
static
void
agp_3_
0
_dev_list_insert
(
struct
list_head
*
head
,
struct
list_head
*
new
)
static
void
agp_3_
5
_dev_list_insert
(
struct
list_head
*
head
,
struct
list_head
*
new
)
{
{
struct
agp_3_
0_dev
*
cur
,
*
n
=
list_entry
(
new
,
struct
agp_3_0
_dev
,
list
);
struct
agp_3_
5_dev
*
cur
,
*
n
=
list_entry
(
new
,
struct
agp_3_5
_dev
,
list
);
struct
list_head
*
pos
;
struct
list_head
*
pos
;
list_for_each
(
pos
,
head
)
{
list_for_each
(
pos
,
head
)
{
cur
=
list_entry
(
pos
,
struct
agp_3_
0
_dev
,
list
);
cur
=
list_entry
(
pos
,
struct
agp_3_
5
_dev
,
list
);
if
(
cur
->
maxbw
>
n
->
maxbw
)
if
(
cur
->
maxbw
>
n
->
maxbw
)
break
;
break
;
}
}
list_add_tail
(
new
,
pos
);
list_add_tail
(
new
,
pos
);
}
}
static
void
agp_3_
0_dev_list_sort
(
struct
agp_3_0
_dev
*
list
,
unsigned
int
ndevs
)
static
void
agp_3_
5_dev_list_sort
(
struct
agp_3_5
_dev
*
list
,
unsigned
int
ndevs
)
{
{
struct
agp_3_
0
_dev
*
cur
;
struct
agp_3_
5
_dev
*
cur
;
struct
pci_dev
*
dev
;
struct
pci_dev
*
dev
;
struct
list_head
*
pos
,
*
tmp
,
*
head
=
&
list
->
list
,
*
start
=
head
->
next
;
struct
list_head
*
pos
,
*
tmp
,
*
head
=
&
list
->
list
,
*
start
=
head
->
next
;
u32
nistat
;
u32
nistat
;
INIT_LIST_HEAD
(
head
);
INIT_LIST_HEAD
(
head
);
for
(
pos
=
start
;
pos
!=
head
;
)
{
for
(
pos
=
start
;
pos
!=
head
;
)
{
cur
=
list_entry
(
pos
,
struct
agp_3_
0
_dev
,
list
);
cur
=
list_entry
(
pos
,
struct
agp_3_
5
_dev
,
list
);
dev
=
cur
->
dev
;
dev
=
cur
->
dev
;
pci_read_config_dword
(
dev
,
cur
->
capndx
+
0x0c
,
&
nistat
);
pci_read_config_dword
(
dev
,
cur
->
capndx
+
AGPNISTAT
,
&
nistat
);
cur
->
maxbw
=
(
nistat
>>
16
)
&
0xff
;
cur
->
maxbw
=
(
nistat
>>
16
)
&
0xff
;
tmp
=
pos
;
tmp
=
pos
;
pos
=
pos
->
next
;
pos
=
pos
->
next
;
agp_3_
0
_dev_list_insert
(
head
,
tmp
);
agp_3_
5
_dev_list_insert
(
head
,
tmp
);
}
}
}
}
...
@@ -59,8 +59,8 @@ static void agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs)
...
@@ -59,8 +59,8 @@ static void agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs)
* lying behind it...)
* lying behind it...)
*/
*/
static
int
agp_3_
0
_isochronous_node_enable
(
struct
agp_bridge_data
*
bridge
,
static
int
agp_3_
5
_isochronous_node_enable
(
struct
agp_bridge_data
*
bridge
,
struct
agp_3_
0
_dev
*
dev_list
,
unsigned
int
ndevs
)
struct
agp_3_
5
_dev
*
dev_list
,
unsigned
int
ndevs
)
{
{
/*
/*
* Convenience structure to make the calculations clearer
* Convenience structure to make the calculations clearer
...
@@ -72,12 +72,12 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -72,12 +72,12 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
u32
y
;
u32
y
;
u32
l
;
u32
l
;
u32
rq
;
u32
rq
;
struct
agp_3_
0
_dev
*
dev
;
struct
agp_3_
5
_dev
*
dev
;
};
};
struct
pci_dev
*
td
=
bridge
->
dev
,
*
dev
;
struct
pci_dev
*
td
=
bridge
->
dev
,
*
dev
;
struct
list_head
*
head
=
&
dev_list
->
list
,
*
pos
;
struct
list_head
*
head
=
&
dev_list
->
list
,
*
pos
;
struct
agp_3_
0
_dev
*
cur
;
struct
agp_3_
5
_dev
*
cur
;
struct
isoch_data
*
master
,
target
;
struct
isoch_data
*
master
,
target
;
unsigned
int
cdev
=
0
;
unsigned
int
cdev
=
0
;
u32
mnistat
,
tnistat
,
tstatus
,
mcmd
;
u32
mnistat
,
tnistat
,
tstatus
,
mcmd
;
...
@@ -91,7 +91,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -91,7 +91,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
* We'll work with an array of isoch_data's (one for each
* We'll work with an array of isoch_data's (one for each
* device in dev_list) throughout this function.
* device in dev_list) throughout this function.
*/
*/
if
((
master
=
kmalloc
(
ndevs
*
sizeof
(
*
master
),
GFP_KERNEL
))
==
NULL
)
{
if
((
master
=
kmalloc
(
ndevs
*
sizeof
(
*
master
),
GFP_KERNEL
))
==
NULL
)
{
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
get_out
;
goto
get_out
;
}
}
...
@@ -112,9 +112,9 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -112,9 +112,9 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
* transfers are enabled and consequently whether maxbw will mean
* transfers are enabled and consequently whether maxbw will mean
* anything.
* anything.
*/
*/
agp_3_
0
_dev_list_sort
(
dev_list
,
ndevs
);
agp_3_
5
_dev_list_sort
(
dev_list
,
ndevs
);
pci_read_config_dword
(
td
,
bridge
->
capndx
+
0x0c
,
&
tnistat
);
pci_read_config_dword
(
td
,
bridge
->
capndx
+
AGPNISTAT
,
&
tnistat
);
pci_read_config_dword
(
td
,
bridge
->
capndx
+
AGPSTAT
,
&
tstatus
);
pci_read_config_dword
(
td
,
bridge
->
capndx
+
AGPSTAT
,
&
tstatus
);
/* Extract power-on defaults from the target */
/* Extract power-on defaults from the target */
...
@@ -132,12 +132,12 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -132,12 +132,12 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
* by these devices and the largest requested payload size.
* by these devices and the largest requested payload size.
*/
*/
list_for_each
(
pos
,
head
)
{
list_for_each
(
pos
,
head
)
{
cur
=
list_entry
(
pos
,
struct
agp_3_
0
_dev
,
list
);
cur
=
list_entry
(
pos
,
struct
agp_3_
5
_dev
,
list
);
dev
=
cur
->
dev
;
dev
=
cur
->
dev
;
mcapndx
=
cur
->
capndx
;
mcapndx
=
cur
->
capndx
;
pci_read_config_dword
(
dev
,
cur
->
capndx
+
0x0c
,
&
mnistat
);
pci_read_config_dword
(
dev
,
cur
->
capndx
+
AGPNISTAT
,
&
mnistat
);
master
[
cdev
].
maxbw
=
(
mnistat
>>
16
)
&
0xff
;
master
[
cdev
].
maxbw
=
(
mnistat
>>
16
)
&
0xff
;
master
[
cdev
].
n
=
(
mnistat
>>
8
)
&
0xff
;
master
[
cdev
].
n
=
(
mnistat
>>
8
)
&
0xff
;
...
@@ -151,7 +151,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -151,7 +151,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
}
}
/* Check if this configuration has any chance of working */
/* Check if this configuration has any chance of working */
if
(
tot_bw
>
target
.
maxbw
)
{
if
(
tot_bw
>
target
.
maxbw
)
{
printk
(
KERN_ERR
PFX
"isochronous bandwidth required "
printk
(
KERN_ERR
PFX
"isochronous bandwidth required "
"by AGP 3.0 devices exceeds that which is supported by "
"by AGP 3.0 devices exceeds that which is supported by "
"the AGP 3.0 bridge!
\n
"
);
"the AGP 3.0 bridge!
\n
"
);
...
@@ -167,17 +167,17 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -167,17 +167,17 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
* in the target's NISTAT register, so we need to do this now
* in the target's NISTAT register, so we need to do this now
* to get an accurate value for ISOCH_N later.
* to get an accurate value for ISOCH_N later.
*/
*/
pci_read_config_word
(
td
,
bridge
->
capndx
+
0x20
,
&
tnicmd
);
pci_read_config_word
(
td
,
bridge
->
capndx
+
AGPNICMD
,
&
tnicmd
);
tnicmd
&=
~
(
0x3
<<
6
);
tnicmd
&=
~
(
0x3
<<
6
);
tnicmd
|=
target
.
y
<<
6
;
tnicmd
|=
target
.
y
<<
6
;
pci_write_config_word
(
td
,
bridge
->
capndx
+
0x20
,
tnicmd
);
pci_write_config_word
(
td
,
bridge
->
capndx
+
AGPNICMD
,
tnicmd
);
/* Reread the target's ISOCH_N */
/* Reread the target's ISOCH_N */
pci_read_config_dword
(
td
,
bridge
->
capndx
+
0x0c
,
&
tnistat
);
pci_read_config_dword
(
td
,
bridge
->
capndx
+
AGPNISTAT
,
&
tnistat
);
target
.
n
=
(
tnistat
>>
8
)
&
0xff
;
target
.
n
=
(
tnistat
>>
8
)
&
0xff
;
/* Calculate the minimum ISOCH_N needed by each master */
/* Calculate the minimum ISOCH_N needed by each master */
for
(
cdev
=
0
;
cdev
<
ndevs
;
cdev
++
)
{
for
(
cdev
=
0
;
cdev
<
ndevs
;
cdev
++
)
{
master
[
cdev
].
y
=
target
.
y
;
master
[
cdev
].
y
=
target
.
y
;
master
[
cdev
].
n
=
master
[
cdev
].
maxbw
/
(
master
[
cdev
].
y
+
1
);
master
[
cdev
].
n
=
master
[
cdev
].
maxbw
/
(
master
[
cdev
].
y
+
1
);
...
@@ -186,7 +186,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -186,7 +186,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
/* Exit if the minimal ISOCH_N allocation among the masters is more
/* Exit if the minimal ISOCH_N allocation among the masters is more
* than the target can handle. */
* than the target can handle. */
if
(
tot_n
>
target
.
n
)
{
if
(
tot_n
>
target
.
n
)
{
printk
(
KERN_ERR
PFX
"number of isochronous "
printk
(
KERN_ERR
PFX
"number of isochronous "
"transactions per period required by AGP 3.0 devices "
"transactions per period required by AGP 3.0 devices "
"exceeds that which is supported by the AGP 3.0 "
"exceeds that which is supported by the AGP 3.0 "
...
@@ -204,7 +204,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -204,7 +204,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
* Along the way, distribute the extra ISOCH_N capability calculated
* Along the way, distribute the extra ISOCH_N capability calculated
* above.
* above.
*/
*/
for
(
cdev
=
0
;
cdev
<
ndevs
;
cdev
++
)
{
for
(
cdev
=
0
;
cdev
<
ndevs
;
cdev
++
)
{
/*
/*
* This is a little subtle. If ISOCH_Y > 64B, then ISOCH_Y
* This is a little subtle. If ISOCH_Y > 64B, then ISOCH_Y
* byte isochronous writes will be broken into 64B pieces.
* byte isochronous writes will be broken into 64B pieces.
...
@@ -213,13 +213,12 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -213,13 +213,12 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
* many writes on the AGP bus).
* many writes on the AGP bus).
*/
*/
master
[
cdev
].
rq
=
master
[
cdev
].
n
;
master
[
cdev
].
rq
=
master
[
cdev
].
n
;
if
(
master
[
cdev
].
y
>
0x1
)
{
if
(
master
[
cdev
].
y
>
0x1
)
master
[
cdev
].
rq
*=
(
1
<<
(
master
[
cdev
].
y
-
1
));
master
[
cdev
].
rq
*=
(
1
<<
(
master
[
cdev
].
y
-
1
));
}
tot_rq
+=
master
[
cdev
].
rq
;
tot_rq
+=
master
[
cdev
].
rq
;
if
(
cdev
==
ndevs
-
1
)
if
(
cdev
==
ndevs
-
1
)
master
[
cdev
].
n
+=
rem
;
master
[
cdev
].
n
+=
rem
;
}
}
...
@@ -230,7 +229,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -230,7 +229,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
/* Exit if the minimal RQ needs of the masters exceeds what the target
/* Exit if the minimal RQ needs of the masters exceeds what the target
* can provide. */
* can provide. */
if
(
tot_rq
>
rq_isoch
)
{
if
(
tot_rq
>
rq_isoch
)
{
printk
(
KERN_ERR
PFX
"number of request queue slots "
printk
(
KERN_ERR
PFX
"number of request queue slots "
"required by the isochronous bandwidth requested by "
"required by the isochronous bandwidth requested by "
"AGP 3.0 devices exceeds the number provided by the "
"AGP 3.0 devices exceeds the number provided by the "
...
@@ -247,7 +246,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -247,7 +246,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
/* Distribute the extra RQ slots calculated above and write our
/* Distribute the extra RQ slots calculated above and write our
* isochronous settings out to the actual devices. */
* isochronous settings out to the actual devices. */
for
(
cdev
=
0
;
cdev
<
ndevs
;
cdev
++
)
{
for
(
cdev
=
0
;
cdev
<
ndevs
;
cdev
++
)
{
cur
=
master
[
cdev
].
dev
;
cur
=
master
[
cdev
].
dev
;
dev
=
cur
->
dev
;
dev
=
cur
->
dev
;
...
@@ -256,7 +255,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -256,7 +255,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
master
[
cdev
].
rq
+=
(
cdev
==
ndevs
-
1
)
master
[
cdev
].
rq
+=
(
cdev
==
ndevs
-
1
)
?
(
rem_async
+
rem_isoch
)
:
step
;
?
(
rem_async
+
rem_isoch
)
:
step
;
pci_read_config_word
(
dev
,
cur
->
capndx
+
0x20
,
&
mnicmd
);
pci_read_config_word
(
dev
,
cur
->
capndx
+
AGPNICMD
,
&
mnicmd
);
pci_read_config_dword
(
dev
,
cur
->
capndx
+
AGPCMD
,
&
mcmd
);
pci_read_config_dword
(
dev
,
cur
->
capndx
+
AGPCMD
,
&
mcmd
);
mnicmd
&=
~
(
0xff
<<
8
);
mnicmd
&=
~
(
0xff
<<
8
);
...
@@ -268,7 +267,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -268,7 +267,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
mcmd
|=
master
[
cdev
].
rq
<<
24
;
mcmd
|=
master
[
cdev
].
rq
<<
24
;
pci_write_config_dword
(
dev
,
cur
->
capndx
+
AGPCMD
,
mcmd
);
pci_write_config_dword
(
dev
,
cur
->
capndx
+
AGPCMD
,
mcmd
);
pci_write_config_word
(
dev
,
cur
->
capndx
+
0x20
,
mnicmd
);
pci_write_config_word
(
dev
,
cur
->
capndx
+
AGPNICMD
,
mnicmd
);
}
}
free_and_exit:
free_and_exit:
...
@@ -285,24 +284,24 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -285,24 +284,24 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
* target by ndevs. Distribute this many slots to each AGP 3.0 device,
* target by ndevs. Distribute this many slots to each AGP 3.0 device,
* giving any left over slots to the last device in dev_list.
* giving any left over slots to the last device in dev_list.
*/
*/
static
void
agp_3_
0
_nonisochronous_node_enable
(
struct
agp_bridge_data
*
bridge
,
static
void
agp_3_
5
_nonisochronous_node_enable
(
struct
agp_bridge_data
*
bridge
,
struct
agp_3_
0
_dev
*
dev_list
,
unsigned
int
ndevs
)
struct
agp_3_
5
_dev
*
dev_list
,
unsigned
int
ndevs
)
{
{
struct
agp_3_
0
_dev
*
cur
;
struct
agp_3_
5
_dev
*
cur
;
struct
list_head
*
head
=
&
dev_list
->
list
,
*
pos
;
struct
list_head
*
head
=
&
dev_list
->
list
,
*
pos
;
u32
tstatus
,
mcmd
;
u32
tstatus
,
mcmd
;
u32
trq
,
mrq
,
rem
;
u32
trq
,
mrq
,
rem
;
unsigned
int
cdev
=
0
;
unsigned
int
cdev
=
0
;
pci_read_config_dword
(
bridge
->
dev
,
bridge
->
capndx
+
0x04
,
&
tstatus
);
pci_read_config_dword
(
bridge
->
dev
,
bridge
->
capndx
+
AGPSTAT
,
&
tstatus
);
trq
=
(
tstatus
>>
24
)
&
0xff
;
trq
=
(
tstatus
>>
24
)
&
0xff
;
mrq
=
trq
/
ndevs
;
mrq
=
trq
/
ndevs
;
rem
=
mrq
+
(
trq
%
ndevs
);
rem
=
mrq
+
(
trq
%
ndevs
);
for
(
pos
=
head
->
next
;
cdev
<
ndevs
;
cdev
++
,
pos
=
pos
->
next
)
{
for
(
pos
=
head
->
next
;
cdev
<
ndevs
;
cdev
++
,
pos
=
pos
->
next
)
{
cur
=
list_entry
(
pos
,
struct
agp_3_
0
_dev
,
list
);
cur
=
list_entry
(
pos
,
struct
agp_3_
5
_dev
,
list
);
pci_read_config_dword
(
cur
->
dev
,
cur
->
capndx
+
AGPCMD
,
&
mcmd
);
pci_read_config_dword
(
cur
->
dev
,
cur
->
capndx
+
AGPCMD
,
&
mcmd
);
mcmd
&=
~
(
0xff
<<
24
);
mcmd
&=
~
(
0xff
<<
24
);
...
@@ -315,24 +314,32 @@ static void agp_3_0_nonisochronous_node_enable(struct agp_bridge_data *bridge,
...
@@ -315,24 +314,32 @@ static void agp_3_0_nonisochronous_node_enable(struct agp_bridge_data *bridge,
* Fully configure and enable an AGP 3.0 host bridge and all the devices
* Fully configure and enable an AGP 3.0 host bridge and all the devices
* lying behind it.
* lying behind it.
*/
*/
int
agp_3_
0_node_enable
(
struct
agp_bridge_data
*
bridge
,
u32
mode
,
u32
minor
)
int
agp_3_
5_enable
(
struct
agp_bridge_data
*
bridge
,
u32
mode
)
{
{
struct
pci_dev
*
td
=
bridge
->
dev
,
*
dev
;
struct
pci_dev
*
td
=
bridge
->
dev
,
*
dev
;
u8
mcapndx
;
u8
mcapndx
;
u32
isoch
,
arqsz
,
cal_cycle
,
tmp
,
rate
;
u32
isoch
,
arqsz
;
u32
tstatus
,
tcmd
,
mcmd
,
mstatus
,
ncapid
;
u32
tstatus
,
mstatus
,
ncapid
;
u32
mmajor
,
mminor
;
u32
mmajor
;
u16
mpstat
;
u16
mpstat
;
struct
agp_3_
0
_dev
*
dev_list
,
*
cur
;
struct
agp_3_
5
_dev
*
dev_list
,
*
cur
;
struct
list_head
*
head
,
*
pos
;
struct
list_head
*
head
,
*
pos
;
unsigned
int
ndevs
=
0
;
unsigned
int
ndevs
=
0
;
int
ret
=
0
;
int
ret
=
0
;
/* Extract some power-on defaults from the target */
pci_read_config_dword
(
td
,
bridge
->
capndx
+
AGPSTAT
,
&
tstatus
);
isoch
=
(
tstatus
>>
17
)
&
0x1
;
if
(
isoch
==
0
)
/* isoch xfers not available, bail out. */
return
-
ENODEV
;
arqsz
=
(
tstatus
>>
13
)
&
0x7
;
/*
/*
* Allocate a head for our AGP 3.
0 device list (multiple AGP 3.0
* Allocate a head for our AGP 3.
5 device list
* devices are allowed behind a single bridge).
*
(multiple AGP v3
devices are allowed behind a single bridge).
*/
*/
if
((
dev_list
=
kmalloc
(
sizeof
(
*
dev_list
),
GFP_KERNEL
))
==
NULL
)
{
if
((
dev_list
=
kmalloc
(
sizeof
(
*
dev_list
),
GFP_KERNEL
))
==
NULL
)
{
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
get_out
;
goto
get_out
;
}
}
...
@@ -342,6 +349,9 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
...
@@ -342,6 +349,9 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
/* Find all AGP devices, and add them to dev_list. */
/* Find all AGP devices, and add them to dev_list. */
pci_for_each_dev
(
dev
)
{
pci_for_each_dev
(
dev
)
{
mcapndx
=
pci_find_capability
(
dev
,
PCI_CAP_ID_AGP
);
mcapndx
=
pci_find_capability
(
dev
,
PCI_CAP_ID_AGP
);
if
(
mcapndx
==
0
)
continue
;
switch
((
dev
->
class
>>
8
)
&
0xff00
)
{
switch
((
dev
->
class
>>
8
)
&
0xff00
)
{
case
0x0600
:
/* Bridge */
case
0x0600
:
/* Bridge */
/* Skip bridges. We should call this function for each one. */
/* Skip bridges. We should call this function for each one. */
...
@@ -357,9 +367,6 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
...
@@ -357,9 +367,6 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
case
0x0300
:
/* Display controller */
case
0x0300
:
/* Display controller */
case
0x0400
:
/* Multimedia controller */
case
0x0400
:
/* Multimedia controller */
if
(
mcapndx
==
0
)
continue
;
if
((
cur
=
kmalloc
(
sizeof
(
*
cur
),
GFP_KERNEL
))
==
NULL
)
{
if
((
cur
=
kmalloc
(
sizeof
(
*
cur
),
GFP_KERNEL
))
==
NULL
)
{
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
free_and_exit
;
goto
free_and_exit
;
...
@@ -376,51 +383,41 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
...
@@ -376,51 +383,41 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
}
}
}
}
/* Extract some power-on defaults from the target */
pci_read_config_dword
(
td
,
bridge
->
capndx
+
0x04
,
&
tstatus
);
isoch
=
(
tstatus
>>
17
)
&
0x1
;
arqsz
=
(
tstatus
>>
13
)
&
0x7
;
cal_cycle
=
(
tstatus
>>
10
)
&
0x7
;
rate
=
tstatus
&
0x7
;
/*
/*
* Take an initial pass through the devices lying behind our host
* Take an initial pass through the devices lying behind our host
* bridge. Make sure each one is actually an AGP 3.0 device, otherwise
* bridge. Make sure each one is actually an AGP 3.0 device, otherwise
* exit with an error message. Along the way store the AGP 3.0
* exit with an error message. Along the way store the AGP 3.0
* cap_ptr for each device, the minimum supported cal_cycle, and the
* cap_ptr for each device
* minimum supported data rate.
*/
*/
list_for_each
(
pos
,
head
)
{
list_for_each
(
pos
,
head
)
{
cur
=
list_entry
(
pos
,
struct
agp_3_
0
_dev
,
list
);
cur
=
list_entry
(
pos
,
struct
agp_3_
5
_dev
,
list
);
dev
=
cur
->
dev
;
dev
=
cur
->
dev
;
pci_read_config_word
(
dev
,
PCI_STATUS
,
&
mpstat
);
pci_read_config_word
(
dev
,
PCI_STATUS
,
&
mpstat
);
if
((
mpstat
&
PCI_STATUS_CAP_LIST
)
==
0
)
if
((
mpstat
&
PCI_STATUS_CAP_LIST
)
==
0
)
continue
;
continue
;
pci_read_config_byte
(
dev
,
PCI_CAPABILITY_LIST
,
&
mcapndx
);
pci_read_config_byte
(
dev
,
PCI_CAPABILITY_LIST
,
&
mcapndx
);
if
(
mcapndx
!=
0
x00
)
{
if
(
mcapndx
!=
0
)
{
do
{
do
{
pci_read_config_dword
(
dev
,
mcapndx
,
&
ncapid
);
pci_read_config_dword
(
dev
,
mcapndx
,
&
ncapid
);
if
((
ncapid
&
0xff
)
!=
0x0
2
)
if
((
ncapid
&
0xff
)
!=
2
)
mcapndx
=
(
ncapid
>>
8
)
&
0xff
;
mcapndx
=
(
ncapid
>>
8
)
&
0xff
;
}
}
while
(((
ncapid
&
0xff
)
!=
0x02
)
&&
(
mcapndx
!=
0x0
0
));
while
(((
ncapid
&
0xff
)
!=
2
)
&&
(
mcapndx
!=
0
));
}
}
if
(
mcapndx
==
0
)
{
if
(
mcapndx
==
0
)
{
printk
(
KERN_ERR
PFX
"woah! Non-AGP device "
printk
(
KERN_ERR
PFX
"woah! Non-AGP device "
"found on the secondary bus of an AGP 3.
0
bridge!
\n
"
);
"found on the secondary bus of an AGP 3.
5
bridge!
\n
"
);
ret
=
-
ENODEV
;
ret
=
-
ENODEV
;
goto
free_and_exit
;
goto
free_and_exit
;
}
}
mmajor
=
(
ncapid
>>
AGP_MAJOR_VERSION_SHIFT
)
&
0xf
;
mmajor
=
(
ncapid
>>
AGP_MAJOR_VERSION_SHIFT
)
&
0xf
;
mminor
=
(
ncapid
>>
AGP_MINOR_VERSION_SHIFT
)
&
0xf
;
if
(
mmajor
<
3
)
{
if
(
mmajor
<
3
)
{
printk
(
KERN_ERR
PFX
"woah! AGP 2.0 device "
printk
(
KERN_ERR
PFX
"woah! AGP 2.0 device "
"found on the secondary bus of an AGP 3.
0
"
"found on the secondary bus of an AGP 3.
5
"
"bridge operating with AGP 3.0 electricals!
\n
"
);
"bridge operating with AGP 3.0 electricals!
\n
"
);
ret
=
-
ENODEV
;
ret
=
-
ENODEV
;
goto
free_and_exit
;
goto
free_and_exit
;
...
@@ -428,101 +425,37 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
...
@@ -428,101 +425,37 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
cur
->
capndx
=
mcapndx
;
cur
->
capndx
=
mcapndx
;
pci_read_config_dword
(
dev
,
cur
->
capndx
+
0x04
,
&
mstatus
);
pci_read_config_dword
(
dev
,
cur
->
capndx
+
AGPSTAT
,
&
mstatus
);
if
(((
mstatus
>>
3
)
&
0x1
)
==
0
)
{
if
(((
mstatus
>>
3
)
&
0x1
)
==
0
)
{
printk
(
KERN_ERR
PFX
"woah! AGP 3.
0
device "
printk
(
KERN_ERR
PFX
"woah! AGP 3.
x
device "
"not operating in AGP 3.
0
mode found on the "
"not operating in AGP 3.
x
mode found on the "
"secondary bus of an AGP 3.
0
bridge operating "
"secondary bus of an AGP 3.
5
bridge operating "
"with AGP 3.0 electricals!
\n
"
);
"with AGP 3.0 electricals!
\n
"
);
ret
=
-
ENODEV
;
ret
=
-
ENODEV
;
goto
free_and_exit
;
goto
free_and_exit
;
}
}
tmp
=
(
mstatus
>>
10
)
&
0x7
;
cal_cycle
=
min
(
cal_cycle
,
tmp
);
/* figure the lesser rate */
tmp
=
mstatus
&
0x7
;
if
(
tmp
<
rate
)
rate
=
tmp
;
}
}
/* Turn rate into something we can actually write out to AGPCMD */
switch
(
rate
)
{
case
0x1
:
case
0x2
:
break
;
case
0x3
:
rate
=
0x2
;
break
;
default:
printk
(
KERN_ERR
PFX
"woah! Bogus AGP rate (%d) "
"value found advertised behind an AGP 3.0 bridge!
\n
"
,
rate
);
ret
=
-
ENODEV
;
goto
free_and_exit
;
}
/*
/*
* Call functions to divide target resources amongst the AGP 3.0
* Call functions to divide target resources amongst the AGP 3.0
* masters. This process is dramatically different depending on
* masters. This process is dramatically different depending on
* whether isochronous transfers are supported.
* whether isochronous transfers are supported.
*/
*/
if
(
isoch
)
{
if
(
isoch
)
{
ret
=
agp_3_
0
_isochronous_node_enable
(
bridge
,
dev_list
,
ndevs
);
ret
=
agp_3_
5
_isochronous_node_enable
(
bridge
,
dev_list
,
ndevs
);
if
(
ret
)
{
if
(
ret
)
{
printk
(
KERN_INFO
PFX
"Something bad happened setting "
printk
(
KERN_INFO
PFX
"Something bad happened setting "
"up isochronous xfers. Falling back to "
"up isochronous xfers. Falling back to "
"non-isochronous xfer mode.
\n
"
);
"non-isochronous xfer mode.
\n
"
);
}
}
}
}
agp_3_0_nonisochronous_node_enable
(
bridge
,
dev_list
,
ndevs
);
agp_3_5_nonisochronous_node_enable
(
bridge
,
dev_list
,
ndevs
);
/*
* Set the calculated minimum supported cal_cycle and minimum
* supported transfer rate in the target's AGPCMD register.
* Also set the AGP_ENABLE bit, effectively 'turning on' the
* target (this has to be done _before_ turning on the masters).
*/
pci_read_config_dword
(
td
,
bridge
->
capndx
+
AGPCMD
,
&
tcmd
);
tcmd
&=
~
(
0x7
<<
10
);
tcmd
&=
~
0x7
;
tcmd
|=
cal_cycle
<<
10
;
tcmd
|=
0x1
<<
8
;
tcmd
|=
rate
;
pci_write_config_dword
(
td
,
bridge
->
capndx
+
AGPCMD
,
tcmd
);
/*
* Set the target's advertised arqsz value, the minimum supported
* transfer rate, and the AGP_ENABLE bit in each master's AGPCMD
* register.
*/
list_for_each
(
pos
,
head
)
{
cur
=
list_entry
(
pos
,
struct
agp_3_0_dev
,
list
);
dev
=
cur
->
dev
;
mcapndx
=
cur
->
capndx
;
pci_read_config_dword
(
dev
,
cur
->
capndx
+
AGPCMD
,
&
mcmd
);
mcmd
&=
~
(
0x7
<<
AGPSTAT_ARQSZ_SHIFT
);
mcmd
&=
~
0x7
;
mcmd
|=
arqsz
<<
13
;
mcmd
|=
AGPSTAT_AGP_ENABLE
;
mcmd
|=
rate
;
pci_write_config_dword
(
dev
,
cur
->
capndx
+
AGPCMD
,
mcmd
);
}
free_and_exit:
free_and_exit:
/* Be sure to free the dev_list */
/* Be sure to free the dev_list */
for
(
pos
=
head
->
next
;
pos
!=
head
;
)
{
for
(
pos
=
head
->
next
;
pos
!=
head
;
)
{
cur
=
list_entry
(
pos
,
struct
agp_3_
0
_dev
,
list
);
cur
=
list_entry
(
pos
,
struct
agp_3_
5
_dev
,
list
);
pos
=
pos
->
next
;
pos
=
pos
->
next
;
kfree
(
cur
);
kfree
(
cur
);
...
@@ -533,5 +466,3 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
...
@@ -533,5 +466,3 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
return
ret
;
return
ret
;
}
}
EXPORT_SYMBOL_GPL
(
agp_3_0_node_enable
);
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