Add simple support for AGP 3.0 including enabling 8x mode. The simple

part of the support is that it still assumes one master and one target
where as AGP 3.0 actually supports multiple devices on the bus.

Submitted by:	Keith Whitwell <keith@tungstengraphics.com>
Sponsored by:	The Weather Channel
This commit is contained in:
John Baldwin 2003-10-23 18:08:56 +00:00
parent 56f88dba4c
commit 9f9ccd206d
3 changed files with 239 additions and 31 deletions

View File

@ -278,18 +278,83 @@ agp_generic_detach(device_t dev)
return 0;
}
int
agp_generic_enable(device_t dev, u_int32_t mode)
/*
* This does the enable logic for v3, with the same topology
* restrictions as in place for v2 -- one bus, one device on the bus.
*/
static int
agp_v3_enable(device_t dev, device_t mdev, u_int32_t mode)
{
device_t mdev = agp_find_display();
u_int32_t tstatus, mstatus;
u_int32_t command;
int rq, sba, fw, rate;;
int rq, sba, fw, rate, arqsz, cal;
if (!mdev) {
AGP_DPF("can't find display\n");
return ENXIO;
}
tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
/* Set RQ to the min of mode, tstatus and mstatus */
rq = AGP_MODE_GET_RQ(mode);
if (AGP_MODE_GET_RQ(tstatus) < rq)
rq = AGP_MODE_GET_RQ(tstatus);
if (AGP_MODE_GET_RQ(mstatus) < rq)
rq = AGP_MODE_GET_RQ(mstatus);
/*
* ARQSZ - Set the value to the maximum one.
* Don't allow the mode register to override values.
*/
arqsz = AGP_MODE_GET_ARQSZ(mode);
if (AGP_MODE_GET_ARQSZ(tstatus) > rq)
rq = AGP_MODE_GET_ARQSZ(tstatus);
if (AGP_MODE_GET_ARQSZ(mstatus) > rq)
rq = AGP_MODE_GET_ARQSZ(mstatus);
/* Calibration cycle - don't allow override by mode register */
cal = AGP_MODE_GET_CAL(tstatus);
if (AGP_MODE_GET_CAL(mstatus) < cal)
cal = AGP_MODE_GET_CAL(mstatus);
/* SBA must be supported for AGP v3. */
sba = 1;
/* Set FW if all three support it. */
fw = (AGP_MODE_GET_FW(tstatus)
& AGP_MODE_GET_FW(mstatus)
& AGP_MODE_GET_FW(mode));
/* Figure out the max rate */
rate = (AGP_MODE_GET_RATE(tstatus)
& AGP_MODE_GET_RATE(mstatus)
& AGP_MODE_GET_RATE(mode));
if (rate & AGP_MODE_V3_RATE_8x)
rate = AGP_MODE_V3_RATE_8x;
else
rate = AGP_MODE_V3_RATE_4x;
if (bootverbose)
device_printf(dev, "Setting AGP v3 mode %d\n", rate * 4);
pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, 0, 4);
/* Construct the new mode word and tell the hardware */
command = AGP_MODE_SET_RQ(0, rq);
command = AGP_MODE_SET_ARQSZ(command, arqsz);
command = AGP_MODE_SET_CAL(command, cal);
command = AGP_MODE_SET_SBA(command, sba);
command = AGP_MODE_SET_FW(command, fw);
command = AGP_MODE_SET_RATE(command, rate);
command = AGP_MODE_SET_AGP(command, 1);
pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, command, 4);
pci_write_config(mdev, agp_find_caps(mdev) + AGP_COMMAND, command, 4);
return 0;
}
static int
agp_v2_enable(device_t dev, device_t mdev, u_int32_t mode)
{
u_int32_t tstatus, mstatus;
u_int32_t command;
int rq, sba, fw, rate;
tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
@ -315,12 +380,14 @@ agp_generic_enable(device_t dev, u_int32_t mode)
rate = (AGP_MODE_GET_RATE(tstatus)
& AGP_MODE_GET_RATE(mstatus)
& AGP_MODE_GET_RATE(mode));
if (rate & AGP_MODE_RATE_4x)
rate = AGP_MODE_RATE_4x;
else if (rate & AGP_MODE_RATE_2x)
rate = AGP_MODE_RATE_2x;
if (rate & AGP_MODE_V2_RATE_4x)
rate = AGP_MODE_V2_RATE_4x;
else if (rate & AGP_MODE_V2_RATE_2x)
rate = AGP_MODE_V2_RATE_2x;
else
rate = AGP_MODE_RATE_1x;
rate = AGP_MODE_V2_RATE_1x;
if (bootverbose)
device_printf(dev, "Setting AGP v2 mode %d\n", rate);
/* Construct the new mode word and tell the hardware */
command = AGP_MODE_SET_RQ(0, rq);
@ -334,6 +401,34 @@ agp_generic_enable(device_t dev, u_int32_t mode)
return 0;
}
int
agp_generic_enable(device_t dev, u_int32_t mode)
{
device_t mdev = agp_find_display();
u_int32_t tstatus, mstatus;
if (!mdev) {
AGP_DPF("can't find display\n");
return ENXIO;
}
tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
/*
* Check display and bridge for AGP v3 support. AGP v3 allows
* more variety in topology than v2, e.g. multiple AGP devices
* attached to one bridge, or multiple AGP bridges in one
* system. This doesn't attempt to address those situations,
* but should work fine for a classic single AGP slot system
* with AGP v3.
*/
if (AGP_MODE_GET_MODE_3(tstatus) && AGP_MODE_GET_MODE_3(mstatus))
return (agp_v3_enable(dev, mdev, mode));
else
return (agp_v2_enable(dev, mdev, mode));
}
struct agp_memory *
agp_generic_alloc_memory(device_t dev, int type, vm_size_t size)
{

View File

@ -278,18 +278,83 @@ agp_generic_detach(device_t dev)
return 0;
}
int
agp_generic_enable(device_t dev, u_int32_t mode)
/*
* This does the enable logic for v3, with the same topology
* restrictions as in place for v2 -- one bus, one device on the bus.
*/
static int
agp_v3_enable(device_t dev, device_t mdev, u_int32_t mode)
{
device_t mdev = agp_find_display();
u_int32_t tstatus, mstatus;
u_int32_t command;
int rq, sba, fw, rate;;
int rq, sba, fw, rate, arqsz, cal;
if (!mdev) {
AGP_DPF("can't find display\n");
return ENXIO;
}
tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
/* Set RQ to the min of mode, tstatus and mstatus */
rq = AGP_MODE_GET_RQ(mode);
if (AGP_MODE_GET_RQ(tstatus) < rq)
rq = AGP_MODE_GET_RQ(tstatus);
if (AGP_MODE_GET_RQ(mstatus) < rq)
rq = AGP_MODE_GET_RQ(mstatus);
/*
* ARQSZ - Set the value to the maximum one.
* Don't allow the mode register to override values.
*/
arqsz = AGP_MODE_GET_ARQSZ(mode);
if (AGP_MODE_GET_ARQSZ(tstatus) > rq)
rq = AGP_MODE_GET_ARQSZ(tstatus);
if (AGP_MODE_GET_ARQSZ(mstatus) > rq)
rq = AGP_MODE_GET_ARQSZ(mstatus);
/* Calibration cycle - don't allow override by mode register */
cal = AGP_MODE_GET_CAL(tstatus);
if (AGP_MODE_GET_CAL(mstatus) < cal)
cal = AGP_MODE_GET_CAL(mstatus);
/* SBA must be supported for AGP v3. */
sba = 1;
/* Set FW if all three support it. */
fw = (AGP_MODE_GET_FW(tstatus)
& AGP_MODE_GET_FW(mstatus)
& AGP_MODE_GET_FW(mode));
/* Figure out the max rate */
rate = (AGP_MODE_GET_RATE(tstatus)
& AGP_MODE_GET_RATE(mstatus)
& AGP_MODE_GET_RATE(mode));
if (rate & AGP_MODE_V3_RATE_8x)
rate = AGP_MODE_V3_RATE_8x;
else
rate = AGP_MODE_V3_RATE_4x;
if (bootverbose)
device_printf(dev, "Setting AGP v3 mode %d\n", rate * 4);
pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, 0, 4);
/* Construct the new mode word and tell the hardware */
command = AGP_MODE_SET_RQ(0, rq);
command = AGP_MODE_SET_ARQSZ(command, arqsz);
command = AGP_MODE_SET_CAL(command, cal);
command = AGP_MODE_SET_SBA(command, sba);
command = AGP_MODE_SET_FW(command, fw);
command = AGP_MODE_SET_RATE(command, rate);
command = AGP_MODE_SET_AGP(command, 1);
pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, command, 4);
pci_write_config(mdev, agp_find_caps(mdev) + AGP_COMMAND, command, 4);
return 0;
}
static int
agp_v2_enable(device_t dev, device_t mdev, u_int32_t mode)
{
u_int32_t tstatus, mstatus;
u_int32_t command;
int rq, sba, fw, rate;
tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
@ -315,12 +380,14 @@ agp_generic_enable(device_t dev, u_int32_t mode)
rate = (AGP_MODE_GET_RATE(tstatus)
& AGP_MODE_GET_RATE(mstatus)
& AGP_MODE_GET_RATE(mode));
if (rate & AGP_MODE_RATE_4x)
rate = AGP_MODE_RATE_4x;
else if (rate & AGP_MODE_RATE_2x)
rate = AGP_MODE_RATE_2x;
if (rate & AGP_MODE_V2_RATE_4x)
rate = AGP_MODE_V2_RATE_4x;
else if (rate & AGP_MODE_V2_RATE_2x)
rate = AGP_MODE_V2_RATE_2x;
else
rate = AGP_MODE_RATE_1x;
rate = AGP_MODE_V2_RATE_1x;
if (bootverbose)
device_printf(dev, "Setting AGP v2 mode %d\n", rate);
/* Construct the new mode word and tell the hardware */
command = AGP_MODE_SET_RQ(0, rq);
@ -334,6 +401,34 @@ agp_generic_enable(device_t dev, u_int32_t mode)
return 0;
}
int
agp_generic_enable(device_t dev, u_int32_t mode)
{
device_t mdev = agp_find_display();
u_int32_t tstatus, mstatus;
if (!mdev) {
AGP_DPF("can't find display\n");
return ENXIO;
}
tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
/*
* Check display and bridge for AGP v3 support. AGP v3 allows
* more variety in topology than v2, e.g. multiple AGP devices
* attached to one bridge, or multiple AGP bridges in one
* system. This doesn't attempt to address those situations,
* but should work fine for a classic single AGP slot system
* with AGP v3.
*/
if (AGP_MODE_GET_MODE_3(tstatus) && AGP_MODE_GET_MODE_3(mstatus))
return (agp_v3_enable(dev, mdev, mode));
else
return (agp_v2_enable(dev, mdev, mode));
}
struct agp_memory *
agp_generic_alloc_memory(device_t dev, int type, vm_size_t size)
{

View File

@ -42,20 +42,38 @@
* FW = Fast Writes
*/
#define AGP_MODE_GET_RQ(x) (((x) & 0xff000000U) >> 24)
#define AGP_MODE_GET_ARQSZ(x) (((x) & 0x0000e000U) >> 13)
#define AGP_MODE_GET_CAL(x) (((x) & 0x00001c00U) >> 10)
#define AGP_MODE_GET_SBA(x) (((x) & 0x00000200U) >> 9)
#define AGP_MODE_GET_AGP(x) (((x) & 0x00000100U) >> 8)
#define AGP_MODE_GET_4G(x) (((x) & 0x00000020U) >> 5)
#define AGP_MODE_GET_GART_64(x) (((x) & 0x00000080U) >> 7)
#define AGP_MODE_GET_OVER_4G(x) (((x) & 0x00000020U) >> 5)
#define AGP_MODE_GET_FW(x) (((x) & 0x00000010U) >> 4)
#define AGP_MODE_GET_MODE_3(x) (((x) & 0x00000008U) >> 3)
#define AGP_MODE_GET_RATE(x) ((x) & 0x00000007U)
#define AGP_MODE_SET_RQ(x,v) (((x) & ~0xff000000U) | ((v) << 24))
#define AGP_MODE_SET_ARQSZ(x,v) (((x) & ~0x0000e000U) | ((v) << 13))
#define AGP_MODE_SET_CAL(x,v) (((x) & ~0x00001c00U) | ((v) << 10))
#define AGP_MODE_SET_SBA(x,v) (((x) & ~0x00000200U) | ((v) << 9))
#define AGP_MODE_SET_AGP(x,v) (((x) & ~0x00000100U) | ((v) << 8))
#define AGP_MODE_SET_4G(x,v) (((x) & ~0x00000020U) | ((v) << 5))
#define AGP_MODE_SET_GART_64(x,v) (((x) & ~0x00000080U) | ((v) << 7))
#define AGP_MODE_SET_OVER_4G(x,v) (((x) & ~0x00000020U) | ((v) << 5))
#define AGP_MODE_SET_FW(x,v) (((x) & ~0x00000010U) | ((v) << 4))
#define AGP_MODE_SET_MODE_3(x,v) (((x) & ~0x00000008U) | ((v) << 3))
#define AGP_MODE_SET_RATE(x,v) (((x) & ~0x00000007U) | (v))
#define AGP_MODE_RATE_1x 0x00000001
#define AGP_MODE_RATE_2x 0x00000002
#define AGP_MODE_RATE_4x 0x00000004
#define AGP_MODE_V2_RATE_1x 0x00000001
#define AGP_MODE_V2_RATE_2x 0x00000002
#define AGP_MODE_V2_RATE_4x 0x00000004
#define AGP_MODE_V3_RATE_4x 0x00000001
#define AGP_MODE_V3_RATE_8x 0x00000002
#define AGP_MODE_V3_RATE_RSVD 0x00000004
/* XXX: Compat */
#define AGP_MODE_GET_4G(x) AGP_MODE_GET_OVER_4G(x)
#define AGP_MODE_SET_4G(x) AGP_MODE_SET_OVER_4G(x)
#define AGP_MODE_RATE_1x AGP_MODE_V2_RATE_1x
#define AGP_MODE_RATE_2x AGP_MODE_V2_RATE_2x
#define AGP_MODE_RATE_4x AGP_MODE_V2_RATE_4x
#define AGPIOC_BASE 'A'
#define AGPIOC_INFO _IOR (AGPIOC_BASE, 0, agp_info)