Subject: agp_i810.c and i965
To: None <port-i386@NetBSD.org>
From: Mark Davies <mark@mcs.vuw.ac.nz>
List: port-i386
Date: 02/17/2007 01:24:16
I'm trying to add support for the i965 to the agp driver.

I initially made the the obvious additions to treat the 965 like the 
915 and 945 but that failed in agp_map_aperture() with 
  pci_mem_find: expected mem type 00000000, found 00000004
Changing the type used by pci_mapreg_info() (for the 965) to 
PCI_MAPREG_MEM_TYPE_64BIT got past that but then it failed in the 
pci_mapreg_map() for the  AGP_I915_GTTADR.

Looking at the linux intel-agp.c which does have support for the 965 I 
see that they do basically this for the 915:

  pci_read_config_dword(intel_i830_private.i830_dev,
                        I915_MMADR,&temp);
  pci_read_config_dword(intel_i830_private.i830_dev,
                        I915_GTTADR,&temp2);

  intel_i830_private.gtt = ioremap(temp2, 256 * 1024);

  temp &= 0xfff80000;
  intel_i830_private.registers = ioremap(temp,128 * 4096);

  temp = readl(intel_i830_private.registers+I810_PGTBL_CTL) & 
0xfffff000;
  global_cache_flush(); 
  pci_read_config_word(agp_bridge->dev,I830_GCC1,&gmch_ctrl);
  size = agp_bridge->driver->fetch_size() + 4;

  gtt_entries = MB(XX) - KB(size);


while for the 965 they do:

  pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADR,
                        &temp);

  temp &= 0xfff00000;
  intel_i830_private.gtt =
          ioremap((temp + (512 * 1024)) , 512 * 1024);

  intel_i830_private.registers = ioremap(temp,128 * 4096);

  temp = readl(intel_i830_private.registers+I810_PGTBL_CTL) & 
0xfffff000;
  global_cache_flush(); 
  pci_read_config_word(agp_bridge->dev,I830_GCC1,&gmch_ctrl);
  pci_read_config_dword(agp_bridge->dev, I810_PGTBL_CTL,
                                 &pgetbl_ctl);
  /* The 965 has a field telling us the size of the GTT,
   * which may be larger than what is necessary to map the
   * aperture.
   */
  switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
  case I965_PGETBL_SIZE_128KB:
          size = 128;
          break;
  case I965_PGETBL_SIZE_256KB:
          size = 256;
          break;
  case I965_PGETBL_SIZE_512KB:
          size = 512;
          break;
  default:
          printk(KERN_INFO PFX "Unknown page table size, "
                    "assuming 512KB\n");
          size = 512;
  }
  size += 4; /* add in BIOS popup space */

  gtt_entries = MB(XX) - KB(size);


So among other things they don't use the GTTADR registers at all.


Now the NetBSD agp does this for 915:

  error = pci_mapreg_map(&isc->vga_pa, AGP_I915_MMADR,
     PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, NULL, NULL);
  error = pci_mapreg_map(&isc->vga_pa, AGP_I915_GTTADR,
     PCI_MAPREG_TYPE_MEM, 0, &isc->gtt_bst, &isc->gtt_bsh,
     NULL, NULL);
  isc->initial_aperture = AGP_GET_APERTURE(sc);
  gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
  gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT;


where get_aperture for i915 is

  reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I915_MSAC);
  msac = (u_int16_t)(reg >> 16);
  if (msac & AGP_I915_MSAC_APER_128M)
      return 128 * 1024 * 1024;
  else
      return 256 * 1024 * 1024;


and at various points calls WRITEGTT() which is defined as

#define WRITEGTT(off, v)						\
  do {							\
    if (isc->chiptype == CHIP_I915)	{		\
       bus_space_write_4(isc->gtt_bst, isc->gtt_bsh,	\
           (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4,	\
           (v));					\
    } else {						\
       WRITE4(AGP_I810_GTT +				\
           (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4,	\
           (v));					\
    }							\
  } while (0)


Being an absolute beginner at agp, pci and bus_space I need some help 
to map the differences in the linux handling of 915/965 to our 
driver.

So for the 965 the call to pci_mapreg_map(..,AGP_I915_GTTADR,..) goes 
away and the WRITEGTT() becomes a WRITE4() but what base offset?
And I'm not sure ag_entries is set right.  What else?

cheers
mark