static void nvidia_cleanup(void) { struct aper_size_info_8 *previous_size; u32 temp; /* gart control */ pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, &temp); pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp & ~(0x100)); /* gtlb control */ pci_read_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, &temp); pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp & ~(0x11)); /* unmap aperture */ iounmap((void __iomem *) nvidia_private.aperture); /* restore previous aperture size */ previous_size = A_SIZE_8(agp_bridge->previous_size); pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE, previous_size->size_value); /* restore iorr for previous aperture size */ nvidia_init_iorr(agp_bridge->gart_bus_addr, previous_size->size * 1024 * 1024); }
static int agp_nvidia_detach (device_t dev) { struct agp_nvidia_softc *sc = device_get_softc(dev); u_int32_t temp; agp_free_cdev(dev); /* GART Control */ temp = pci_read_config(sc->dev, AGP_NVIDIA_0_APSIZE, 4); pci_write_config(sc->dev, AGP_NVIDIA_0_APSIZE, temp & ~(0x100), 4); /* GTLB Control */ temp = pci_read_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, 4); pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, temp & ~(0x11), 4); /* Put the aperture back the way it started. */ AGP_SET_APERTURE(dev, sc->initial_aperture); /* restore iorr for previous aperture size */ nvidia_init_iorr(rman_get_start(sc->agp.as_aperture), sc->initial_aperture); agp_free_gatt(sc->gatt); agp_free_res(dev); return (0); }
static int nvidia_configure(void) { int i, rc, num_dirs; u32 apbase, aplimit; struct aper_size_info_8 *current_size; u32 temp; current_size = A_SIZE_8(agp_bridge->current_size); /* aperture size */ pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE, current_size->size_value); /* address to map to */ pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &apbase); apbase &= PCI_BASE_ADDRESS_MEM_MASK; agp_bridge->gart_bus_addr = apbase; aplimit = apbase + (current_size->size * 1024 * 1024) - 1; pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APBASE, apbase); pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APLIMIT, aplimit); pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APBASE, apbase); pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APLIMIT, aplimit); if (0 != (rc = nvidia_init_iorr(apbase, current_size->size * 1024 * 1024))) return rc; /* directory size is 64k */ num_dirs = current_size->size / 64; nvidia_private.num_active_entries = current_size->num_entries; nvidia_private.pg_offset = 0; if (num_dirs == 0) { num_dirs = 1; nvidia_private.num_active_entries /= (64 / current_size->size); nvidia_private.pg_offset = (apbase & (64 * 1024 * 1024 - 1) & ~(current_size->size * 1024 * 1024 - 1)) / PAGE_SIZE; } /* attbase */ for (i = 0; i < 8; i++) { pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_ATTBASE(i), (agp_bridge->gatt_bus_addr + (i % num_dirs) * 64 * 1024) | 1); } /* gtlb control */ pci_read_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, &temp); pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp | 0x11); /* gart control */ pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, &temp); pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp | 0x100); /* map aperture */ nvidia_private.aperture = (volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE); if (!nvidia_private.aperture) return -ENOMEM; return 0; }
static int agp_nvidia_attach (device_t dev) { struct agp_nvidia_softc *sc = device_get_softc(dev); struct agp_gatt *gatt; u_int32_t apbase; u_int32_t aplimit; u_int32_t temp; int size; int i; int error; switch (pci_get_device(dev)) { case NVIDIA_DEVICEID_NFORCE: sc->wbc_mask = 0x00010000; break; case NVIDIA_DEVICEID_NFORCE2: sc->wbc_mask = 0x80000000; break; default: device_printf(dev, "Bad chip id\n"); return (ENODEV); } /* AGP Controller */ sc->dev = dev; /* Memory Controller 1 */ sc->mc1_dev = pci_find_bsf(pci_get_bus(dev), 0, 1); if (sc->mc1_dev == NULL) { device_printf(dev, "Unable to find NVIDIA Memory Controller 1.\n"); return (ENODEV); } /* Memory Controller 2 */ sc->mc2_dev = pci_find_bsf(pci_get_bus(dev), 0, 2); if (sc->mc2_dev == NULL) { device_printf(dev, "Unable to find NVIDIA Memory Controller 2.\n"); return (ENODEV); } /* AGP Host to PCI Bridge */ sc->bdev = pci_find_bsf(pci_get_bus(dev), 30, 0); if (sc->bdev == NULL) { device_printf(dev, "Unable to find NVIDIA AGP Host to PCI Bridge.\n"); return (ENODEV); } error = agp_generic_attach(dev); if (error) return (error); sc->initial_aperture = AGP_GET_APERTURE(dev); if (sc->initial_aperture == 0) { device_printf(dev, "bad initial aperture size, disabling\n"); return ENXIO; } for (;;) { gatt = agp_alloc_gatt(dev); if (gatt) break; /* * Probably contigmalloc failure. Try reducing the * aperture so that the gatt size reduces. */ if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) goto fail; } sc->gatt = gatt; apbase = rman_get_start(sc->agp.as_aperture); aplimit = apbase + AGP_GET_APERTURE(dev) - 1; pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_APBASE, apbase, 4); pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_APLIMIT, aplimit, 4); pci_write_config(sc->bdev, AGP_NVIDIA_3_APBASE, apbase, 4); pci_write_config(sc->bdev, AGP_NVIDIA_3_APLIMIT, aplimit, 4); error = nvidia_init_iorr(apbase, AGP_GET_APERTURE(dev)); if (error) { device_printf(dev, "Failed to setup IORRs\n"); goto fail; } /* directory size is 64k */ size = AGP_GET_APERTURE(dev) / 1024 / 1024; sc->num_dirs = size / 64; sc->num_active_entries = (size == 32) ? 16384 : ((size * 1024) / 4); sc->pg_offset = 0; if (sc->num_dirs == 0) { sc->num_dirs = 1; sc->num_active_entries /= (64 / size); sc->pg_offset = (apbase & (64 * 1024 * 1024 - 1) & ~(AGP_GET_APERTURE(dev) - 1)) / PAGE_SIZE; } /* (G)ATT Base Address */ for (i = 0; i < 8; i++) { pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_ATTBASE(i), (sc->gatt->ag_physical + (i % sc->num_dirs) * 64 * 1024) | 1, 4); } /* GTLB Control */ temp = pci_read_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, 4); pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, temp | 0x11, 4); /* GART Control */ temp = pci_read_config(sc->dev, AGP_NVIDIA_0_APSIZE, 4); pci_write_config(sc->dev, AGP_NVIDIA_0_APSIZE, temp | 0x100, 4); return (0); fail: agp_generic_detach(dev); return (ENOMEM); }