2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
#include "types.h"
|
2008-12-09 04:41:11 +01:00
|
|
|
#include "link.h"
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <malloc.h>
|
|
|
|
#include <memory.h>
|
|
|
|
|
|
|
|
#include "pci.h"
|
|
|
|
#include "agp.h"
|
|
|
|
|
|
|
|
#include "syscall.h"
|
|
|
|
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
agp_t *bridge;
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
int __stdcall srv_agp(ioctl_t *io);
|
|
|
|
|
|
|
|
|
|
|
|
u32_t __stdcall drvEntry(int action)
|
|
|
|
{
|
|
|
|
u32_t retval;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if(action != 1)
|
|
|
|
return 0;
|
|
|
|
|
2022-01-06 20:34:04 +01:00
|
|
|
if(!dbg_open("/sys/drivers/agp.log"))
|
2008-12-08 07:22:59 +01:00
|
|
|
{
|
2022-01-06 20:34:04 +01:00
|
|
|
printf("Can't open /sys/drivers/agp.log\nExit\n");
|
2008-12-08 07:22:59 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( FindPciDevice() == 0)
|
|
|
|
{
|
|
|
|
dbgprintf("Device not found\n");
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// retval = RegService("AGP", srv_2d);
|
|
|
|
// dbgprintf("reg service %s as: %x\n", "HDRAW", retval);
|
|
|
|
|
|
|
|
// return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
#include "pci.inc"
|
2008-12-12 13:33:09 +01:00
|
|
|
#include "isoch.inc"
|
2008-12-09 04:41:11 +01:00
|
|
|
|
2008-12-08 07:22:59 +01:00
|
|
|
static void intel_8xx_tlbflush(void *mem)
|
|
|
|
{
|
|
|
|
u32_t temp;
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
temp = pciReadLong(bridge->PciTag, INTEL_AGPCTRL);
|
|
|
|
pciWriteLong(bridge->PciTag, INTEL_AGPCTRL, temp & ~(1 << 7));
|
|
|
|
temp = pciReadLong(bridge->PciTag, INTEL_AGPCTRL);
|
|
|
|
pciWriteLong(bridge->PciTag, INTEL_AGPCTRL, temp | (1 << 7));
|
2008-12-08 07:22:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static aper_size_t intel_8xx_sizes[7] =
|
|
|
|
{
|
|
|
|
{ 256, 65536, 64, 0 },
|
|
|
|
{ 128, 32768, 32, 32 },
|
|
|
|
{ 64, 16384, 16, 48 },
|
|
|
|
{ 32, 8192, 8, 56 },
|
|
|
|
{ 16, 4096, 4, 60 },
|
|
|
|
{ 8, 2048, 2, 62 },
|
|
|
|
{ 4, 1024, 1, 63 }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
static int intel_845_configure()
|
2008-12-08 07:22:59 +01:00
|
|
|
{
|
|
|
|
u32_t temp;
|
|
|
|
u8_t temp2;
|
|
|
|
aper_size_t *current_size;
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
current_size = bridge->current_size;
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
/* aperture size */
|
2008-12-09 04:41:11 +01:00
|
|
|
pciWriteByte(bridge->PciTag, INTEL_APSIZE, current_size->size_value);
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
dbgprintf("INTEL_APSIZE %d\n", current_size->size_value );
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
if (bridge->apbase_config != 0)
|
2008-12-08 07:22:59 +01:00
|
|
|
{
|
2008-12-09 04:41:11 +01:00
|
|
|
pciWriteLong(bridge->PciTag, AGP_APBASE, bridge->apbase_config);
|
2008-12-08 07:22:59 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* address to map to */
|
2008-12-09 04:41:11 +01:00
|
|
|
temp = pciReadLong(bridge->PciTag, AGP_APBASE);
|
|
|
|
bridge->gart_addr = (temp & PCI_MAP_MEMORY_ADDRESS_MASK);
|
|
|
|
bridge->apbase_config = temp;
|
2008-12-08 07:22:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
dbgprintf("AGP_APBASE %x\n", temp );
|
|
|
|
|
|
|
|
/* attbase - aperture base */
|
2008-12-09 04:41:11 +01:00
|
|
|
pciWriteLong(bridge->PciTag, INTEL_ATTBASE, bridge->gatt_dma);
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
/* agpctrl */
|
2008-12-09 04:41:11 +01:00
|
|
|
pciWriteLong(bridge->PciTag, INTEL_AGPCTRL, 0x0000);
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
/* agpm */
|
2008-12-09 04:41:11 +01:00
|
|
|
temp2 = pciReadByte(bridge->PciTag, INTEL_I845_AGPM);
|
|
|
|
pciWriteByte(bridge->PciTag, INTEL_I845_AGPM, temp2 | (1 << 1));
|
2008-12-08 07:22:59 +01:00
|
|
|
/* clear any possible error conditions */
|
2008-12-09 04:41:11 +01:00
|
|
|
pciWriteWord(bridge->PciTag, INTEL_I845_ERRSTS, 0x001c);
|
2008-12-08 07:22:59 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
int agp_generic_create_gatt_table()
|
2008-12-08 07:22:59 +01:00
|
|
|
{
|
|
|
|
count_t pages;
|
|
|
|
|
|
|
|
pages = bridge->current_size->pages_count;
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
if( bridge->gatt_dma = AllocPages(pages))
|
|
|
|
{
|
|
|
|
if(bridge->gatt_table =
|
|
|
|
(u32_t*)MapIoMem((void*)bridge->gatt_dma,
|
|
|
|
pages<<12, PG_SW+PG_NOCACHE))
|
|
|
|
{
|
|
|
|
dbgprintf("gatt map %x at %x %d pages\n",bridge->gatt_dma ,
|
|
|
|
bridge->gatt_table, pages);
|
2008-12-08 07:22:59 +01:00
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
/* AK: bogus, should encode addresses > 4GB */
|
2008-12-08 07:22:59 +01:00
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
u32_t volatile *table = bridge->gatt_table;
|
2008-12-08 07:22:59 +01:00
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
count_t count = bridge->current_size->num_entries;
|
2008-12-08 07:22:59 +01:00
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
while(count--) { /* FIXME memset */
|
|
|
|
addr_t tmp;
|
2008-12-08 07:22:59 +01:00
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
*table = 0;
|
|
|
|
table++;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
dbgprintf("unable to get memory for "
|
|
|
|
"graphics translation table.\n");
|
2008-12-08 07:22:59 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int __intel_8xx_fetch_size(u8_t temp)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
aper_size_t *values;
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
values = bridge->aperture_sizes;
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
values = intel_8xx_sizes;
|
|
|
|
|
|
|
|
for (i = 0; i < 7; i++)
|
|
|
|
{
|
|
|
|
if (temp == values[i].size_value)
|
|
|
|
{
|
2008-12-09 04:41:11 +01:00
|
|
|
bridge->previous_size =
|
|
|
|
bridge->current_size = (void *) (values + i);
|
|
|
|
bridge->aperture_size_idx = i;
|
2008-12-08 07:22:59 +01:00
|
|
|
return values[i].size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int intel_8xx_fetch_size(void)
|
|
|
|
{
|
|
|
|
u8_t temp;
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
temp = pciReadByte(bridge->PciTag, INTEL_APSIZE);
|
2008-12-08 07:22:59 +01:00
|
|
|
return __intel_8xx_fetch_size(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int agp_bind_memory(addr_t agp_addr, addr_t dma_addr, size_t size)
|
|
|
|
{
|
|
|
|
int ret_val;
|
|
|
|
count_t count;
|
|
|
|
|
|
|
|
// if (curr == NULL)
|
|
|
|
// return -EINVAL;
|
|
|
|
|
|
|
|
// if (curr->is_bound == TRUE) {
|
|
|
|
// printk(KERN_INFO PFX "memory %p is already bound!\n", curr);
|
|
|
|
// return -EINVAL;
|
|
|
|
// }
|
|
|
|
// if (curr->is_flushed == FALSE) {
|
|
|
|
// curr->bridge->driver->cache_flush();
|
|
|
|
// curr->is_flushed = TRUE;
|
|
|
|
// }
|
|
|
|
// ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
u32_t volatile *table = &bridge->gatt_table[agp_addr>>12];
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
count = size >> 12;
|
|
|
|
|
|
|
|
dma_addr |= 0x00000017;
|
|
|
|
|
|
|
|
while(count--)
|
|
|
|
{
|
|
|
|
*table = dma_addr;
|
|
|
|
table++;
|
|
|
|
dma_addr+=4096;
|
|
|
|
}
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
bridge->tlb_flush(NULL);
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
// if (ret_val != 0)
|
|
|
|
// return ret_val;
|
|
|
|
|
|
|
|
// curr->is_bound = TRUE;
|
|
|
|
// curr->pg_start = pg_start;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
void get_agp_version(agp_t *bridge)
|
|
|
|
{
|
|
|
|
u32_t ncapid;
|
|
|
|
|
|
|
|
/* Exit early if already set by errata workarounds. */
|
|
|
|
if (bridge->major_version != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ncapid = pciReadLong(bridge->PciTag, bridge->capndx);
|
|
|
|
bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;
|
|
|
|
bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void agp_v2_parse_one(u32_t *requested_mode, u32_t *bridge_agpstat, u32_t *vga_agpstat)
|
|
|
|
{
|
|
|
|
u32_t tmp;
|
|
|
|
|
|
|
|
if (*requested_mode & AGP2_RESERVED_MASK) {
|
|
|
|
dbgprintf("reserved bits set (%x) in mode 0x%x. Fixed.\n",
|
|
|
|
*requested_mode & AGP2_RESERVED_MASK, *requested_mode);
|
|
|
|
*requested_mode &= ~AGP2_RESERVED_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check the speed bits make sense. Only one should be set. */
|
|
|
|
tmp = *requested_mode & 7;
|
|
|
|
switch (tmp) {
|
|
|
|
case 0:
|
|
|
|
dbgprintf("Setting to x1 mode.\n");
|
|
|
|
*requested_mode |= AGPSTAT2_1X;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
*requested_mode &= ~(AGPSTAT2_1X); /* rate=2 */
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
case 6:
|
|
|
|
case 7:
|
|
|
|
*requested_mode &= ~(AGPSTAT2_1X|AGPSTAT2_2X); /* rate=4*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* disable SBA if it's not supported */
|
|
|
|
if (!((*bridge_agpstat & AGPSTAT_SBA) && (*vga_agpstat & AGPSTAT_SBA) && (*requested_mode & AGPSTAT_SBA)))
|
|
|
|
*bridge_agpstat &= ~AGPSTAT_SBA;
|
|
|
|
|
|
|
|
/* Set rate */
|
|
|
|
if (!((*bridge_agpstat & AGPSTAT2_4X) && (*vga_agpstat & AGPSTAT2_4X) && (*requested_mode & AGPSTAT2_4X)))
|
|
|
|
*bridge_agpstat &= ~AGPSTAT2_4X;
|
|
|
|
|
|
|
|
if (!((*bridge_agpstat & AGPSTAT2_2X) && (*vga_agpstat & AGPSTAT2_2X) && (*requested_mode & AGPSTAT2_2X)))
|
|
|
|
*bridge_agpstat &= ~AGPSTAT2_2X;
|
|
|
|
|
|
|
|
if (!((*bridge_agpstat & AGPSTAT2_1X) && (*vga_agpstat & AGPSTAT2_1X) && (*requested_mode & AGPSTAT2_1X)))
|
|
|
|
*bridge_agpstat &= ~AGPSTAT2_1X;
|
|
|
|
|
|
|
|
/* Now we know what mode it should be, clear out the unwanted bits. */
|
|
|
|
if (*bridge_agpstat & AGPSTAT2_4X)
|
|
|
|
*bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */
|
|
|
|
|
|
|
|
if (*bridge_agpstat & AGPSTAT2_2X)
|
|
|
|
*bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */
|
|
|
|
|
|
|
|
if (*bridge_agpstat & AGPSTAT2_1X)
|
|
|
|
*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1X */
|
|
|
|
|
|
|
|
/* Apply any errata. */
|
|
|
|
if (bridge->flags & AGP_ERRATA_FASTWRITES)
|
|
|
|
*bridge_agpstat &= ~AGPSTAT_FW;
|
|
|
|
|
|
|
|
if (bridge->flags & AGP_ERRATA_SBA)
|
|
|
|
*bridge_agpstat &= ~AGPSTAT_SBA;
|
|
|
|
|
|
|
|
if (bridge->flags & AGP_ERRATA_1X) {
|
|
|
|
*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
|
|
|
|
*bridge_agpstat |= AGPSTAT2_1X;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we've dropped down to 1X, disable fast writes. */
|
|
|
|
if (*bridge_agpstat & AGPSTAT2_1X)
|
|
|
|
*bridge_agpstat &= ~AGPSTAT_FW;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void agp_v3_parse_one(u32_t *requested_mode,
|
|
|
|
u32_t *bridge_agpstat,
|
|
|
|
u32_t *vga_agpstat)
|
|
|
|
{
|
|
|
|
u32_t origbridge = *bridge_agpstat, origvga = *vga_agpstat;
|
|
|
|
u32_t tmp;
|
|
|
|
|
|
|
|
if (*requested_mode & AGP3_RESERVED_MASK)
|
|
|
|
{
|
|
|
|
dbgprintf("reserved bits set (%x) in mode 0x%x. Fixed.\n",
|
|
|
|
*requested_mode & AGP3_RESERVED_MASK, *requested_mode);
|
|
|
|
*requested_mode &= ~AGP3_RESERVED_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check the speed bits make sense. */
|
|
|
|
tmp = *requested_mode & 7;
|
|
|
|
if (tmp == 0) {
|
|
|
|
dbgprintf("Setting to AGP3 x4 mode.\n");
|
|
|
|
*requested_mode |= AGPSTAT3_4X;
|
|
|
|
}
|
|
|
|
if (tmp >= 3) {
|
|
|
|
dbgprintf("Setting to AGP3 x8 mode.\n");
|
|
|
|
*requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARQSZ - Set the value to the maximum one.
|
|
|
|
* Don't allow the mode register to override values. */
|
|
|
|
*bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_ARQSZ) |
|
|
|
|
max_t(u32_t,(*bridge_agpstat & AGPSTAT_ARQSZ),(*vga_agpstat & AGPSTAT_ARQSZ)));
|
|
|
|
|
|
|
|
/* Calibration cycle.
|
|
|
|
* Don't allow the mode register to override values. */
|
|
|
|
*bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_CAL_MASK) |
|
|
|
|
min_t(u32_t,(*bridge_agpstat & AGPSTAT_CAL_MASK),(*vga_agpstat & AGPSTAT_CAL_MASK)));
|
|
|
|
|
|
|
|
/* SBA *must* be supported for AGP v3 */
|
|
|
|
*bridge_agpstat |= AGPSTAT_SBA;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set speed.
|
|
|
|
* Check for invalid speeds. This can happen when applications
|
|
|
|
* written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware
|
|
|
|
*/
|
|
|
|
if (*requested_mode & AGPSTAT_MODE_3_0) {
|
|
|
|
/*
|
|
|
|
* Caller hasn't a clue what it is doing. Bridge is in 3.0 mode,
|
|
|
|
* have been passed a 3.0 mode, but with 2.x speed bits set.
|
|
|
|
* AGP2.x 4x -> AGP3.0 4x.
|
|
|
|
*/
|
|
|
|
if (*requested_mode & AGPSTAT2_4X) {
|
|
|
|
dbgprintf("broken AGP3 flags (%x). Fixed.\n", *requested_mode);
|
|
|
|
*requested_mode &= ~AGPSTAT2_4X;
|
|
|
|
*requested_mode |= AGPSTAT3_4X;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* The caller doesn't know what they are doing. We are in 3.0 mode,
|
|
|
|
* but have been passed an AGP 2.x mode.
|
|
|
|
* Convert AGP 1x,2x,4x -> AGP 3.0 4x.
|
|
|
|
*/
|
|
|
|
dbgprintf("broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",*requested_mode);
|
|
|
|
*requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
|
|
|
|
*requested_mode |= AGPSTAT3_4X;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*requested_mode & AGPSTAT3_8X) {
|
|
|
|
if (!(*bridge_agpstat & AGPSTAT3_8X)) {
|
|
|
|
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
|
|
|
|
*bridge_agpstat |= AGPSTAT3_4X;
|
|
|
|
dbgprintf("requested AGPx8 but bridge not capable.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!(*vga_agpstat & AGPSTAT3_8X)) {
|
|
|
|
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
|
|
|
|
*bridge_agpstat |= AGPSTAT3_4X;
|
|
|
|
dbgprintf("requested AGPx8 but graphic card not capable.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* All set, bridge & device can do AGP x8*/
|
|
|
|
*bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we didn't specify AGPx8, we can only do x4.
|
|
|
|
* If the hardware can't do x4, we're up shit creek, and never
|
|
|
|
* should have got this far.
|
|
|
|
*/
|
|
|
|
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
|
|
|
|
if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X))
|
|
|
|
*bridge_agpstat |= AGPSTAT3_4X;
|
|
|
|
else {
|
|
|
|
dbgprintf("Badness. Don't know which AGP mode to set. "
|
|
|
|
"[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n",
|
|
|
|
origbridge, origvga, *bridge_agpstat, *vga_agpstat);
|
|
|
|
if (!(*bridge_agpstat & AGPSTAT3_4X))
|
|
|
|
dbgprintf("Bridge couldn't do AGP x4.\n");
|
|
|
|
if (!(*vga_agpstat & AGPSTAT3_4X))
|
|
|
|
dbgprintf("Graphic card couldn't do AGP x4.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
/* Apply any errata. */
|
|
|
|
if (bridge->flags & AGP_ERRATA_FASTWRITES)
|
|
|
|
*bridge_agpstat &= ~AGPSTAT_FW;
|
|
|
|
|
|
|
|
if (bridge->flags & AGP_ERRATA_SBA)
|
|
|
|
*bridge_agpstat &= ~AGPSTAT_SBA;
|
|
|
|
|
|
|
|
if (bridge->flags & AGP_ERRATA_1X) {
|
|
|
|
*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
|
|
|
|
*bridge_agpstat |= AGPSTAT2_1X;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
u32_t agp_collect_device_status(agp_t *bridge, u32_t requested_mode,
|
|
|
|
u32_t bridge_agpstat)
|
|
|
|
{
|
|
|
|
PCITAG vgaTag;
|
|
|
|
u32_t vga_agpstat;
|
|
|
|
int cap_ptr;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
vgaTag = pci_find_class(PCI_CLASS_DISPLAY_VGA);
|
|
|
|
if (vgaTag == -1)
|
|
|
|
{
|
|
|
|
dbgprintf("Couldn't find an AGP VGA controller.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
cap_ptr = pci_find_capability(vgaTag, PCI_CAP_ID_AGP);
|
|
|
|
if (cap_ptr)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ok, here we have a AGP device. Disable impossible
|
|
|
|
* settings, and adjust the readqueue to the minimum.
|
|
|
|
*/
|
|
|
|
vga_agpstat = pciReadLong(vgaTag, cap_ptr+PCI_AGP_STATUS);
|
|
|
|
|
|
|
|
/* adjust RQ depth */
|
|
|
|
bridge_agpstat = ((bridge_agpstat & ~AGPSTAT_RQ_DEPTH) |
|
|
|
|
min_t(u32_t, (requested_mode & AGPSTAT_RQ_DEPTH),
|
|
|
|
min_t(u32_t, (bridge_agpstat & AGPSTAT_RQ_DEPTH), (vga_agpstat & AGPSTAT_RQ_DEPTH))));
|
|
|
|
|
|
|
|
/* disable FW if it's not supported */
|
|
|
|
if (!((bridge_agpstat & AGPSTAT_FW) &&
|
|
|
|
(vga_agpstat & AGPSTAT_FW) &&
|
|
|
|
(requested_mode & AGPSTAT_FW)))
|
|
|
|
bridge_agpstat &= ~AGPSTAT_FW;
|
|
|
|
|
|
|
|
/* Check to see if we are operating in 3.0 mode */
|
|
|
|
if (bridge->mode & AGPSTAT_MODE_3_0)
|
|
|
|
agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
|
|
|
|
else
|
|
|
|
agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
|
|
|
|
|
|
|
|
return bridge_agpstat;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void agp_device_command(u32_t bridge_agpstat, int agp_v3)
|
|
|
|
{
|
|
|
|
PCITAG device = 0;
|
|
|
|
int mode;
|
|
|
|
|
|
|
|
mode = bridge_agpstat & 0x7;
|
|
|
|
if (agp_v3)
|
|
|
|
mode *= 4;
|
|
|
|
|
|
|
|
for_each_pci_dev(device)
|
|
|
|
{
|
|
|
|
int agp = pci_find_capability(device, PCI_CAP_ID_AGP);
|
|
|
|
if (!agp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dbgprintf("Putting AGP V%d device at into %dx mode\n",
|
|
|
|
agp_v3 ? 3 : 2, mode);
|
|
|
|
pciWriteLong(device, agp + PCI_AGP_COMMAND, bridge_agpstat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void agp_generic_enable(u32_t requested_mode)
|
|
|
|
{
|
|
|
|
u32_t bridge_agpstat, temp;
|
|
|
|
|
|
|
|
get_agp_version(bridge);
|
|
|
|
|
|
|
|
dbgprintf("Found an AGP %d.%d compliant device.\n",
|
|
|
|
bridge->major_version, bridge->minor_version);
|
|
|
|
|
|
|
|
bridge_agpstat = pciReadLong(bridge->PciTag,
|
|
|
|
bridge->capndx + PCI_AGP_STATUS);
|
|
|
|
|
|
|
|
bridge_agpstat = agp_collect_device_status(bridge, requested_mode, bridge_agpstat);
|
|
|
|
if (bridge_agpstat == 0)
|
|
|
|
/* Something bad happened. FIXME: Return error code? */
|
|
|
|
return;
|
|
|
|
|
|
|
|
bridge_agpstat |= AGPSTAT_AGP_ENABLE;
|
|
|
|
|
|
|
|
/* Do AGP version specific frobbing. */
|
|
|
|
if (bridge->major_version >= 3)
|
|
|
|
{
|
|
|
|
if (bridge->mode & AGPSTAT_MODE_3_0)
|
|
|
|
{
|
|
|
|
/* If we have 3.5, we can do the isoch stuff. */
|
|
|
|
if (bridge->minor_version >= 5)
|
|
|
|
agp_3_5_enable(bridge);
|
|
|
|
agp_device_command(bridge_agpstat, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/
|
|
|
|
bridge_agpstat &= ~(7<<10) ;
|
|
|
|
temp = pciReadLong(bridge->PciTag, bridge->capndx+AGPCTRL);
|
|
|
|
temp |= (1<<9);
|
|
|
|
pciWriteLong(bridge->PciTag, bridge->capndx+AGPCTRL, temp);
|
|
|
|
|
|
|
|
dbgprintf("Device is in legacy mode,"
|
|
|
|
" falling back to 2.x\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* AGP v<3 */
|
|
|
|
agp_device_command(bridge_agpstat, FALSE);
|
|
|
|
}
|
|
|
|
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
static agp_t intel_845_driver =
|
|
|
|
{
|
2008-12-09 04:41:11 +01:00
|
|
|
.aperture_sizes = intel_8xx_sizes,
|
2008-12-08 07:22:59 +01:00
|
|
|
// .size_type = U8_APER_SIZE,
|
|
|
|
// .num_aperture_sizes = 7,
|
|
|
|
.configure = intel_845_configure,
|
|
|
|
.fetch_size = intel_8xx_fetch_size,
|
|
|
|
// .cleanup = intel_8xx_cleanup,
|
|
|
|
.tlb_flush = intel_8xx_tlbflush,
|
|
|
|
// .mask_memory = agp_generic_mask_memory,
|
|
|
|
// .masks = intel_generic_masks,
|
|
|
|
// .agp_enable = agp_generic_enable,
|
|
|
|
// .cache_flush = global_cache_flush,
|
2008-12-09 04:41:11 +01:00
|
|
|
.create_gatt_table = agp_generic_create_gatt_table,
|
2008-12-08 07:22:59 +01:00
|
|
|
// .free_gatt_table = agp_generic_free_gatt_table,
|
|
|
|
// .insert_memory = agp_generic_insert_memory,
|
|
|
|
// .remove_memory = agp_generic_remove_memory,
|
|
|
|
// .alloc_by_type = agp_generic_alloc_by_type,
|
|
|
|
// .free_by_type = agp_generic_free_by_type,
|
|
|
|
// .agp_alloc_page = agp_generic_alloc_page,
|
|
|
|
// .agp_destroy_page = agp_generic_destroy_page,
|
|
|
|
};
|
|
|
|
|
2008-12-09 04:41:11 +01:00
|
|
|
int init_bridge(PCITAG pciTag)
|
|
|
|
{
|
|
|
|
size_t size_value;
|
|
|
|
|
|
|
|
bridge = &intel_845_driver;
|
|
|
|
|
|
|
|
bridge->PciTag = pciTag;
|
|
|
|
|
|
|
|
bridge->capndx = pci_find_capability(pciTag, PCI_CAP_ID_AGP);
|
|
|
|
|
|
|
|
size_value = bridge->fetch_size();
|
|
|
|
|
|
|
|
if (size_value == 0) {
|
|
|
|
dbgprintf("unable to determine aperture size.\n");
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
dbgprintf("fetch size = %x\n", size_value);
|
|
|
|
|
|
|
|
if( bridge->create_gatt_table() )
|
|
|
|
{
|
|
|
|
bridge->configure();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-12-08 07:22:59 +01:00
|
|
|
|
|
|
|
#include "detect.inc"
|