Commit 1d1be2aa authored by Dave Jones's avatar Dave Jones Committed by Dave Jones

[AGPGART] Add proper AGP3 initialisation routine.

parent 7598a3cf
...@@ -405,14 +405,20 @@ void get_agp_version(struct agp_bridge_data *bridge); ...@@ -405,14 +405,20 @@ void get_agp_version(struct agp_bridge_data *bridge);
#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_AGP_ENABLE (1<<8)
#define AGPSTAT_SBA (1<<9) #define AGPSTAT_SBA (1<<9)
#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 AGPSTAT3_8X (1<<1)
#define AGPSTAT3_4X (1)
#define AGPSTAT_FW (1<<4) #define AGPSTAT_FW (1<<4)
#endif /* _AGP_BACKEND_PRIV_H */ #endif /* _AGP_BACKEND_PRIV_H */
...@@ -366,60 +366,106 @@ EXPORT_SYMBOL(agp_unbind_memory); ...@@ -366,60 +366,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 */
u32 agp_collect_device_status(u32 mode, u32 command) if (*cmd & AGPSTAT2_2X)
*cmd &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */
if (*cmd & AGPSTAT2_1X)
*cmd &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1Xf */
}
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);
if (*cmd & AGPSTAT3_4X)
*cmd *= ~(AGPSTAT3_8X);
}
//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 */
command = ((command & ~AGPSTAT_RQ_DEPTH) | cmd = ((cmd & ~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)))
command &= ~AGPSTAT2_2X;
if (!((command & AGPSTAT2_1X) && (scratch & AGPSTAT2_1X) && (mode & AGPSTAT2_1X))) /* Check to see if we are operating in 3.0 mode */
command &= ~AGPSTAT2_1X; if (agp3 & AGPSTAT_MODE_3_0) {
agp_v3_parse_one(&mode, &cmd, &tmp);
} else {
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);
...@@ -461,47 +507,47 @@ void get_agp_version(struct agp_bridge_data *bridge) ...@@ -461,47 +507,47 @@ void get_agp_version(struct agp_bridge_data *bridge)
EXPORT_SYMBOL(get_agp_version); EXPORT_SYMBOL(get_agp_version);
static int agp_3_0_enable(struct agp_bridge_data *bridge, u32 mode)
{
return 0;
}
void agp_generic_enable(u32 mode) void agp_generic_enable(u32 mode)
{ {
u32 command; u32 command;
u32 agp3;
get_agp_version(agp_bridge); get_agp_version(agp_bridge);
printk(KERN_INFO PFX "Found an AGP %d.%d compliant device.\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->major_version,
agp_bridge->minor_version,
agp_bridge->dev->slot_name);
pci_read_config_dword(agp_bridge->dev,
agp_bridge->capndx + PCI_AGP_STATUS, &command);
command = agp_collect_device_status(mode, command);
command |= AGPSTAT_AGP_ENABLE;
pci_write_config_dword(agp_bridge->dev,
agp_bridge->capndx + PCI_AGP_COMMAND, command);
/* Do AGP version specific frobbing. */
if(agp_bridge->major_version >= 3) { if(agp_bridge->major_version >= 3) {
u32 agp_3_0; pci_read_config_dword(agp_bridge->dev,
agp_bridge->capndx+AGPSTAT, &agp3);
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + 0x4, &agp_3_0);
/* Check to see if we are operating in 3.0 mode */ /* Check to see if we are operating in 3.0 mode */
if((agp_3_0 >> 3) & 0x1) { if (agp3 & AGPSTAT_MODE_3_0) {
if (agp_bridge->minor_version < 5) /* If we have 3.5, we can do the isoch stuff. */
agp_3_0_enable(agp_bridge, mode); if (agp_bridge->minor_version >= 5)
else
agp_3_5_enable(agp_bridge, mode); agp_3_5_enable(agp_bridge, mode);
agp_device_command(command, TRUE);
return; return;
} else { } else {
printk (KERN_INFO PFX "not in AGP 3.0 mode, falling back to 2.x\n"); printk (KERN_INFO PFX "Device is in legacy mode,"
" falling back to 2.x\n");
} }
} }
/* AGP v<3 */ /* AGP v<3 */
pci_read_config_dword(agp_bridge->dev, agp_device_command(command, FALSE);
agp_bridge->capndx + PCI_AGP_STATUS, &command);
command = agp_collect_device_status(mode, command);
command |= AGPSTAT_AGP_ENABLE;
pci_write_config_dword(agp_bridge->dev,
agp_bridge->capndx + PCI_AGP_COMMAND, command);
agp_device_command(command, 0);
} }
EXPORT_SYMBOL(agp_generic_enable); EXPORT_SYMBOL(agp_generic_enable);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment