diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile index 5799759d6194780d7ba2d33a3fea472b071ac3e2..f2466a5944773f15920d50f97fd5df5d02276284 100644 --- a/drivers/char/agp/Makefile +++ b/drivers/char/agp/Makefile @@ -1,4 +1,4 @@ -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_ALI) += ali-agp.o diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 2eb6e4c33b88bb11e34419b7c6cea97bd0b36600..c46fa55faeb6b45b01c1320b8c3609c3f2181763 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -139,6 +139,8 @@ struct agp_bridge_data { int max_memory_agp; /* in number of pages */ int aperture_size_idx; int capndx; + char major_version; + char minor_version; }; #define OUTREG64(mmap, addr, val) __raw_writeq((val), (mmap)+(addr)) @@ -388,27 +390,38 @@ void agp_free_key(int key); int agp_num_entries(void); u32 agp_collect_device_status(u32 mode, u32 command); 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 get_agp_version(struct agp_bridge_data *bridge); /* Standard agp registers */ #define AGPSTAT 0x4 #define AGPCMD 0x8 +#define AGPNISTAT 0xc #define AGPNEPG 0x16 +#define AGPNICMD 0x20 #define AGP_MAJOR_VERSION_SHIFT (20) #define AGP_MINOR_VERSION_SHIFT (16) #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_AGP_ENABLE (1<<8) #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_2X (1<<1) #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 */ diff --git a/drivers/char/agp/amd-k8-agp.c b/drivers/char/agp/amd-k8-agp.c index cfd9e0d7b32d139c8e72db9824cbd201519f7782..81a36f0c985915a38ed68d24d935dac45de2f3f4 100644 --- a/drivers/char/agp/amd-k8-agp.c +++ b/drivers/char/agp/amd-k8-agp.c @@ -253,8 +253,10 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev, { struct agp_bridge_data *bridge; struct pci_dev *loop_dev; + u8 rev_id; u8 cap_ptr; int i = 0; + char *revstring=" "; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); if (!cap_ptr) @@ -266,14 +268,38 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev, if (!bridge) 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->dev = pdev; bridge->capndx = cap_ptr; /* Fill in the mode register */ - pci_read_config_dword(pdev, - bridge->capndx+PCI_AGP_STATUS, - &bridge->mode); + pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode); /* cache pci_devs of northbridges. */ pci_for_each_dev(loop_dev) { @@ -290,7 +316,7 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); - out_free: +out_free: agp_put_bridge(bridge); return -ENOMEM; } diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 3284feb236c97e624423e70658d580ea21d208f3..3f5a3366cf375dc0aa06318230c76dd38e204538 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -270,14 +270,16 @@ EXPORT_SYMBOL_GPL(agp_num_entries); int agp_copy_info(agp_kern_info * info) { memset(info, 0, sizeof(agp_kern_info)); - if (agp_bridge->type == NOT_SUPPORTED) { - info->chipset = agp_bridge->type; + if (!agp_bridge || agp_bridge->type == NOT_SUPPORTED || + !agp_bridge->version) { + info->chipset = NOT_SUPPORTED; return -EIO; } + info->version.major = agp_bridge->version->major; info->version.minor = agp_bridge->version->minor; - info->device = agp_bridge->dev; info->chipset = agp_bridge->type; + info->device = agp_bridge->dev; info->mode = agp_bridge->mode; info->aper_base = agp_bridge->gart_bus_addr; info->aper_size = agp_return_size(); @@ -366,60 +368,106 @@ EXPORT_SYMBOL(agp_unbind_memory); /* 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; - u8 agp; - u32 scratch; + u8 cap_ptr; + u32 tmp; + u32 agp3; pci_for_each_dev(device) { - agp = pci_find_capability(device, PCI_CAP_ID_AGP); - if (!agp) + cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); + if (!cap_ptr) continue; /* * Ok, here we have a AGP device. Disable impossible * 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 */ - command = ((command & ~AGPSTAT_RQ_DEPTH) | + cmd = ((cmd & ~AGPSTAT_RQ_DEPTH) | min_t(u32, (mode & AGPSTAT_RQ_DEPTH), - min_t(u32, (command & AGPSTAT_RQ_DEPTH), - (scratch & AGPSTAT_RQ_DEPTH)))); - - /* 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; + min_t(u32, (cmd & AGPSTAT_RQ_DEPTH), (tmp & AGPSTAT_RQ_DEPTH)))); + + pci_read_config_dword(device, cap_ptr+AGPSTAT, &agp3); - if (!((command & AGPSTAT2_2X) && (scratch & AGPSTAT2_2X) && (mode & AGPSTAT2_2X))) - command &= ~AGPSTAT2_2X; - - if (!((command & AGPSTAT2_1X) && (scratch & AGPSTAT2_1X) && (mode & AGPSTAT2_1X))) - command &= ~AGPSTAT2_1X; + /* Check to see if we are operating in 3.0 mode */ + if (agp3 & AGPSTAT_MODE_3_0) { + agp_v3_parse_one(&mode, &cmd, &tmp); + } else { + agp_v2_parse_one(&mode, &cmd, &tmp); + } } - - /* 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; + return cmd; } EXPORT_SYMBOL(agp_collect_device_status); @@ -446,29 +494,33 @@ void agp_device_command(u32 command, int agp_v3) EXPORT_SYMBOL(agp_device_command); -void agp_generic_enable(u32 mode) +void get_agp_version(struct agp_bridge_data *bridge) { - 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); - major = (ncapid >> 20) & 0xf; - minor = (ncapid >> 16) & 0xf; - printk(KERN_INFO PFX "Found an AGP %d.%d compliant device.\n",major, minor); + agp_bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; + agp_bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf; +} +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); - /* Check to see if we are operating in 3.0 mode */ - if((agp_3_0 >> 3) & 0x1) { - agp_3_0_node_enable(agp_bridge, mode, minor); - return; - } else { - printk (KERN_INFO PFX "not in AGP 3.0 mode, falling back to 2.x\n"); - } - } +void agp_generic_enable(u32 mode) +{ + u32 command; + u32 agp3; + + get_agp_version(agp_bridge); + + 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, agp_bridge->capndx + PCI_AGP_STATUS, &command); @@ -477,7 +529,27 @@ void agp_generic_enable(u32 mode) pci_write_config_dword(agp_bridge->dev, 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); @@ -831,6 +903,7 @@ void agp_enable(u32 mode) } EXPORT_SYMBOL(agp_enable); + #ifdef CONFIG_SMP static void ipi_handler(void *null) { diff --git a/drivers/char/agp/generic-3.0.c b/drivers/char/agp/isoch.c similarity index 66% rename from drivers/char/agp/generic-3.0.c rename to drivers/char/agp/isoch.c index 76f7cb06da0e234115708a77f3a977986791840e..210f305ac93ae9afe25e05b6e320ff01ad192934 100644 --- a/drivers/char/agp/generic-3.0.c +++ b/drivers/char/agp/isoch.c @@ -1,5 +1,5 @@ /* - * Generic routines for AGP 3.0 compliant bridges. + * Setup routines for AGP 3.5 compliant bridges. */ #include <linux/list.h> @@ -9,47 +9,47 @@ #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; u8 capndx; u32 maxbw; 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; 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) break; } 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 list_head *pos, *tmp, *head = &list->list, *start = head->next; u32 nistat; INIT_LIST_HEAD(head); - for(pos = start; pos != head;) { - cur = list_entry(pos, struct agp_3_0_dev, list); + for (pos=start; pos!=head; ) { + cur = list_entry(pos, struct agp_3_5_dev, list); 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; tmp = pos; 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) * lying behind it...) */ -static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge, - struct agp_3_0_dev *dev_list, unsigned int ndevs) +static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, + struct agp_3_5_dev *dev_list, unsigned int ndevs) { /* * Convenience structure to make the calculations clearer @@ -72,12 +72,12 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge, u32 y; u32 l; u32 rq; - struct agp_3_0_dev *dev; + struct agp_3_5_dev *dev; }; struct pci_dev *td = bridge->dev, *dev; 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; unsigned int cdev = 0; u32 mnistat, tnistat, tstatus, mcmd; @@ -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 * 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; goto get_out; } @@ -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 * 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); /* Extract power-on defaults from the target */ @@ -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. */ 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; 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].n = (mnistat >> 8) & 0xff; @@ -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 */ - if(tot_bw > target.maxbw) { + if (tot_bw > target.maxbw) { printk(KERN_ERR PFX "isochronous bandwidth required " "by AGP 3.0 devices exceeds that which is supported by " "the AGP 3.0 bridge!\n"); @@ -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 * 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 |= 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 */ - pci_read_config_dword(td, bridge->capndx + 0x0c, &tnistat); + pci_read_config_dword(td, bridge->capndx+AGPNISTAT, &tnistat); target.n = (tnistat >> 8) & 0xff; /* 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].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, /* Exit if the minimal ISOCH_N allocation among the masters is more * than the target can handle. */ - if(tot_n > target.n) { + if (tot_n > target.n) { printk(KERN_ERR PFX "number of isochronous " "transactions per period required by AGP 3.0 devices " "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, * Along the way, distribute the extra ISOCH_N capability calculated * 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 * 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, * many writes on the AGP bus). */ master[cdev].rq = master[cdev].n; - if(master[cdev].y > 0x1) { + if(master[cdev].y > 0x1) master[cdev].rq *= (1 << (master[cdev].y - 1)); - } tot_rq += master[cdev].rq; - if(cdev == ndevs - 1) + if (cdev == ndevs-1) master[cdev].n += rem; } @@ -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 * can provide. */ - if(tot_rq > rq_isoch) { + if (tot_rq > rq_isoch) { printk(KERN_ERR PFX "number of request queue slots " "required by the isochronous bandwidth requested by " "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, /* Distribute the extra RQ slots calculated above and write our * isochronous settings out to the actual devices. */ - for(cdev = 0; cdev < ndevs; cdev++) { + for (cdev=0; cdev<ndevs; cdev++) { cur = master[cdev].dev; dev = cur->dev; @@ -256,7 +255,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge, master[cdev].rq += (cdev == ndevs - 1) ? (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); mnicmd &= ~(0xff << 8); @@ -268,7 +267,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge, mcmd |= master[cdev].rq << 24; 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: @@ -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, * 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, - struct agp_3_0_dev *dev_list, unsigned int ndevs) +static void agp_3_5_nonisochronous_node_enable(struct agp_bridge_data *bridge, + 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; u32 tstatus, mcmd; u32 trq, mrq, rem; 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; mrq = trq / ndevs; rem = mrq + (trq % ndevs); - for(pos = head->next; cdev < ndevs; cdev++, pos = pos->next) { - cur = list_entry(pos, struct agp_3_0_dev, list); + for (pos=head->next; cdev<ndevs; cdev++, pos=pos->next) { + cur = list_entry(pos, struct agp_3_5_dev, list); pci_read_config_dword(cur->dev, cur->capndx+AGPCMD, &mcmd); mcmd &= ~(0xff << 24); @@ -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 * 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; u8 mcapndx; - u32 isoch, arqsz, cal_cycle, tmp, rate; - u32 tstatus, tcmd, mcmd, mstatus, ncapid; - u32 mmajor, mminor; + u32 isoch, arqsz; + u32 tstatus, mstatus, ncapid; + u32 mmajor; u16 mpstat; - struct agp_3_0_dev *dev_list, *cur; + struct agp_3_5_dev *dev_list, *cur; struct list_head *head, *pos; unsigned int ndevs = 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 - * devices are allowed behind a single bridge). + * Allocate a head for our AGP 3.5 device list + * (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; goto get_out; } @@ -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. */ pci_for_each_dev(dev) { mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP); + if (mcapndx == 0) + continue; + switch ((dev->class >>8) & 0xff00) { case 0x0600: /* Bridge */ /* 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) case 0x0300: /* Display controller */ case 0x0400: /* Multimedia controller */ - if (mcapndx == 0) - continue; - if((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) { ret = -ENOMEM; goto free_and_exit; @@ -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 * 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 - * cap_ptr for each device, the minimum supported cal_cycle, and the - * minimum supported data rate. + * cap_ptr for each device */ 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; pci_read_config_word(dev, PCI_STATUS, &mpstat); - if((mpstat & PCI_STATUS_CAP_LIST) == 0) + if ((mpstat & PCI_STATUS_CAP_LIST) == 0) continue; pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &mcapndx); - if (mcapndx != 0x00) { + if (mcapndx != 0) { do { pci_read_config_dword(dev, mcapndx, &ncapid); - if ((ncapid & 0xff) != 0x02) + if ((ncapid & 0xff) != 2) mcapndx = (ncapid >> 8) & 0xff; } - while (((ncapid & 0xff) != 0x02) && (mcapndx != 0x00)); + while (((ncapid & 0xff) != 2) && (mcapndx != 0)); } - if(mcapndx == 0) { + if (mcapndx == 0) { 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; goto free_and_exit; } 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 " - "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"); ret = -ENODEV; goto free_and_exit; @@ -428,101 +425,37 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor) 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) { - printk(KERN_ERR PFX "woah! AGP 3.0 device " - "not operating in AGP 3.0 mode found on the " - "secondary bus of an AGP 3.0 bridge operating " + if (((mstatus >> 3) & 0x1) == 0) { + printk(KERN_ERR PFX "woah! AGP 3.x device " + "not operating in AGP 3.x mode found on the " + "secondary bus of an AGP 3.5 bridge operating " "with AGP 3.0 electricals!\n"); ret = -ENODEV; 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 * masters. This process is dramatically different depending on * whether isochronous transfers are supported. */ 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) { printk(KERN_INFO PFX "Something bad happened setting " "up isochronous xfers. Falling back to " "non-isochronous xfer mode.\n"); } } - agp_3_0_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); - } + agp_3_5_nonisochronous_node_enable(bridge, dev_list, ndevs); free_and_exit: /* Be sure to free the dev_list */ - for(pos = head->next; pos != head;) { - cur = list_entry(pos, struct agp_3_0_dev, list); + for (pos=head->next; pos!=head; ) { + cur = list_entry(pos, struct agp_3_5_dev, list); pos = pos->next; kfree(cur); @@ -533,5 +466,3 @@ int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor) return ret; } -EXPORT_SYMBOL_GPL(agp_3_0_node_enable); - diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig index 994371de2dc710a2d6d94bf1d6f09a5ebe8d8600..6ec5ca77a95678ebf0c1e9ed23d7313097752729 100644 --- a/drivers/char/drm/Kconfig +++ b/drivers/char/drm/Kconfig @@ -49,7 +49,7 @@ config DRM_RADEON config DRM_I810 tristate "Intel I810" - depends on DRM && AGP + depends on DRM && AGP && AGP_INTEL help Choose this option if you have an Intel I810 graphics card. If M is selected, the module will be called i810. AGP support is required @@ -57,7 +57,7 @@ config DRM_I810 config DRM_I830 tristate "Intel 830M, 845G, 852GM, 855GM, 865G" - depends on DRM && AGP + depends on DRM && AGP && AGP_INTEL help Choose this option if you have a system that has Intel 830M, 845G, 852GM, 855GM or 865G integrated graphics. If M is selected, the