Rev 3746 | Rev 4560 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3746 | Rev 4104 | ||
---|---|---|---|
Line 82... | Line 82... | ||
82 | memset(dmah->vaddr, 0, size); |
82 | memset(dmah->vaddr, 0, size); |
Line 83... | Line 83... | ||
83 | 83 | ||
84 | return dmah; |
84 | return dmah; |
Line -... | Line 85... | ||
- | 85 | } |
|
- | 86 | ||
- | 87 | EXPORT_SYMBOL(drm_pci_alloc); |
|
- | 88 | ||
- | 89 | #if 0 |
|
- | 90 | /** |
|
- | 91 | * \brief Free a PCI consistent memory block without freeing its descriptor. |
|
- | 92 | * |
|
- | 93 | * This function is for internal use in the Linux-specific DRM core code. |
|
- | 94 | */ |
|
- | 95 | void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) |
|
- | 96 | { |
|
- | 97 | unsigned long addr; |
|
- | 98 | size_t sz; |
|
- | 99 | ||
- | 100 | if (dmah->vaddr) { |
|
- | 101 | /* XXX - Is virt_to_page() legal for consistent mem? */ |
|
- | 102 | /* Unreserve */ |
|
- | 103 | for (addr = (unsigned long)dmah->vaddr, sz = dmah->size; |
|
- | 104 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { |
|
- | 105 | ClearPageReserved(virt_to_page(addr)); |
|
- | 106 | } |
|
- | 107 | dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr, |
|
- | 108 | dmah->busaddr); |
|
- | 109 | } |
|
- | 110 | } |
|
- | 111 | ||
- | 112 | /** |
|
- | 113 | * \brief Free a PCI consistent memory block |
|
- | 114 | */ |
|
- | 115 | void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) |
|
- | 116 | { |
|
- | 117 | __drm_pci_free(dev, dmah); |
|
- | 118 | kfree(dmah); |
|
- | 119 | } |
|
- | 120 | ||
- | 121 | EXPORT_SYMBOL(drm_pci_free); |
|
- | 122 | ||
- | 123 | ||
- | 124 | static int drm_get_pci_domain(struct drm_device *dev) |
|
- | 125 | { |
|
- | 126 | #ifndef __alpha__ |
|
- | 127 | /* For historical reasons, drm_get_pci_domain() is busticated |
|
- | 128 | * on most archs and has to remain so for userspace interface |
|
- | 129 | * < 1.4, except on alpha which was right from the beginning |
|
- | 130 | */ |
|
- | 131 | if (dev->if_version < 0x10004) |
|
- | 132 | return 0; |
|
- | 133 | #endif /* __alpha__ */ |
|
- | 134 | ||
- | 135 | return pci_domain_nr(dev->pdev->bus); |
|
- | 136 | } |
|
- | 137 | ||
- | 138 | static int drm_pci_get_irq(struct drm_device *dev) |
|
- | 139 | { |
|
- | 140 | return dev->pdev->irq; |
|
- | 141 | } |
|
- | 142 | ||
- | 143 | static const char *drm_pci_get_name(struct drm_device *dev) |
|
- | 144 | { |
|
- | 145 | struct pci_driver *pdriver = dev->driver->kdriver.pci; |
|
- | 146 | return pdriver->name; |
|
- | 147 | } |
|
- | 148 | ||
- | 149 | static int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master) |
|
- | 150 | { |
|
- | 151 | int len, ret; |
|
- | 152 | struct pci_driver *pdriver = dev->driver->kdriver.pci; |
|
- | 153 | master->unique_len = 40; |
|
- | 154 | master->unique_size = master->unique_len; |
|
- | 155 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); |
|
- | 156 | if (master->unique == NULL) |
|
- | 157 | return -ENOMEM; |
|
- | 158 | ||
- | 159 | ||
- | 160 | len = snprintf(master->unique, master->unique_len, |
|
- | 161 | "pci:%04x:%02x:%02x.%d", |
|
- | 162 | drm_get_pci_domain(dev), |
|
- | 163 | dev->pdev->bus->number, |
|
- | 164 | PCI_SLOT(dev->pdev->devfn), |
|
- | 165 | PCI_FUNC(dev->pdev->devfn)); |
|
- | 166 | ||
- | 167 | if (len >= master->unique_len) { |
|
- | 168 | DRM_ERROR("buffer overflow"); |
|
- | 169 | ret = -EINVAL; |
|
- | 170 | goto err; |
|
- | 171 | } else |
|
- | 172 | master->unique_len = len; |
|
- | 173 | ||
- | 174 | dev->devname = |
|
- | 175 | kmalloc(strlen(pdriver->name) + |
|
- | 176 | master->unique_len + 2, GFP_KERNEL); |
|
- | 177 | ||
- | 178 | if (dev->devname == NULL) { |
|
- | 179 | ret = -ENOMEM; |
|
- | 180 | goto err; |
|
- | 181 | } |
|
- | 182 | ||
- | 183 | sprintf(dev->devname, "%s@%s", pdriver->name, |
|
- | 184 | master->unique); |
|
- | 185 | ||
- | 186 | return 0; |
|
- | 187 | err: |
|
- | 188 | return ret; |
|
- | 189 | } |
|
- | 190 | ||
- | 191 | static int drm_pci_set_unique(struct drm_device *dev, |
|
- | 192 | struct drm_master *master, |
|
- | 193 | struct drm_unique *u) |
|
- | 194 | { |
|
- | 195 | int domain, bus, slot, func, ret; |
|
- | 196 | const char *bus_name; |
|
- | 197 | ||
- | 198 | master->unique_len = u->unique_len; |
|
- | 199 | master->unique_size = u->unique_len + 1; |
|
- | 200 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); |
|
- | 201 | if (!master->unique) { |
|
- | 202 | ret = -ENOMEM; |
|
- | 203 | goto err; |
|
- | 204 | } |
|
- | 205 | ||
- | 206 | if (copy_from_user(master->unique, u->unique, master->unique_len)) { |
|
- | 207 | ret = -EFAULT; |
|
- | 208 | goto err; |
|
- | 209 | } |
|
- | 210 | ||
- | 211 | master->unique[master->unique_len] = '\0'; |
|
- | 212 | ||
- | 213 | bus_name = dev->driver->bus->get_name(dev); |
|
- | 214 | dev->devname = kmalloc(strlen(bus_name) + |
|
- | 215 | strlen(master->unique) + 2, GFP_KERNEL); |
|
- | 216 | if (!dev->devname) { |
|
- | 217 | ret = -ENOMEM; |
|
- | 218 | goto err; |
|
- | 219 | } |
|
- | 220 | ||
- | 221 | sprintf(dev->devname, "%s@%s", bus_name, |
|
- | 222 | master->unique); |
|
- | 223 | ||
- | 224 | /* Return error if the busid submitted doesn't match the device's actual |
|
- | 225 | * busid. |
|
- | 226 | */ |
|
- | 227 | ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func); |
|
- | 228 | if (ret != 3) { |
|
- | 229 | ret = -EINVAL; |
|
- | 230 | goto err; |
|
- | 231 | } |
|
- | 232 | ||
- | 233 | domain = bus >> 8; |
|
- | 234 | bus &= 0xff; |
|
- | 235 | ||
- | 236 | if ((domain != drm_get_pci_domain(dev)) || |
|
- | 237 | (bus != dev->pdev->bus->number) || |
|
- | 238 | (slot != PCI_SLOT(dev->pdev->devfn)) || |
|
- | 239 | (func != PCI_FUNC(dev->pdev->devfn))) { |
|
- | 240 | ret = -EINVAL; |
|
- | 241 | goto err; |
|
- | 242 | } |
|
- | 243 | return 0; |
|
- | 244 | err: |
|
- | 245 | return ret; |
|
- | 246 | } |
|
- | 247 | ||
- | 248 | ||
- | 249 | static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) |
|
- | 250 | { |
|
- | 251 | if ((p->busnum >> 8) != drm_get_pci_domain(dev) || |
|
- | 252 | (p->busnum & 0xff) != dev->pdev->bus->number || |
|
- | 253 | p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn)) |
|
- | 254 | return -EINVAL; |
|
- | 255 | ||
- | 256 | p->irq = dev->pdev->irq; |
|
- | 257 | ||
- | 258 | DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum, |
|
- | 259 | p->irq); |
|
- | 260 | return 0; |
|
- | 261 | } |
|
- | 262 | ||
- | 263 | static int drm_pci_agp_init(struct drm_device *dev) |
|
- | 264 | { |
|
- | 265 | if (drm_core_has_AGP(dev)) { |
|
- | 266 | if (drm_pci_device_is_agp(dev)) |
|
- | 267 | dev->agp = drm_agp_init(dev); |
|
- | 268 | if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) |
|
- | 269 | && (dev->agp == NULL)) { |
|
- | 270 | DRM_ERROR("Cannot initialize the agpgart module.\n"); |
|
- | 271 | return -EINVAL; |
|
- | 272 | } |
|
- | 273 | if (dev->agp) { |
|
- | 274 | dev->agp->agp_mtrr = arch_phys_wc_add( |
|
- | 275 | dev->agp->agp_info.aper_base, |
|
- | 276 | dev->agp->agp_info.aper_size * |
|
- | 277 | 1024 * 1024); |
|
- | 278 | } |
|
- | 279 | } |
|
- | 280 | return 0; |
|
- | 281 | } |
|
- | 282 | ||
- | 283 | static void drm_pci_agp_destroy(struct drm_device *dev) |
|
- | 284 | { |
|
- | 285 | if (drm_core_has_AGP(dev) && dev->agp) { |
|
- | 286 | arch_phys_wc_del(dev->agp->agp_mtrr); |
|
- | 287 | drm_agp_clear(dev); |
|
- | 288 | drm_agp_destroy(dev->agp); |
|
- | 289 | dev->agp = NULL; |
|
- | 290 | } |
|
- | 291 | } |
|
- | 292 | ||
- | 293 | static struct drm_bus drm_pci_bus = { |
|
- | 294 | .bus_type = DRIVER_BUS_PCI, |
|
- | 295 | .get_irq = drm_pci_get_irq, |
|
- | 296 | .get_name = drm_pci_get_name, |
|
- | 297 | .set_busid = drm_pci_set_busid, |
|
- | 298 | .set_unique = drm_pci_set_unique, |
|
- | 299 | .irq_by_busid = drm_pci_irq_by_busid, |
|
- | 300 | .agp_init = drm_pci_agp_init, |
|
- | 301 | .agp_destroy = drm_pci_agp_destroy, |
|
- | 302 | }; |
|
- | 303 | #endif |
|
- | 304 | ||
- | 305 | /** |
|
- | 306 | * Register. |
|
- | 307 | * |
|
- | 308 | * \param pdev - PCI device structure |
|
- | 309 | * \param ent entry from the PCI ID table with device type flags |
|
- | 310 | * \return zero on success or a negative number on failure. |
|
- | 311 | * |
|
- | 312 | * Attempt to gets inter module "drm" information. If we are first |
|
- | 313 | * then register the character device and inter module information. |
|
- | 314 | * Try and register, if we fail to register, backout previous work. |
|
- | 315 | */ |
|
- | 316 | int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, |
|
- | 317 | struct drm_driver *driver) |
|
- | 318 | { |
|
- | 319 | static struct drm_device drm_dev; |
|
- | 320 | static struct drm_file drm_file; |
|
- | 321 | ||
- | 322 | struct drm_device *dev; |
|
- | 323 | struct drm_file *priv; |
|
- | 324 | ||
- | 325 | int ret; |
|
- | 326 | ||
- | 327 | dev = &drm_dev; |
|
- | 328 | priv = &drm_file; |
|
- | 329 | ||
- | 330 | drm_file_handlers[0] = priv; |
|
- | 331 | ||
- | 332 | // ret = pci_enable_device(pdev); |
|
- | 333 | // if (ret) |
|
- | 334 | // goto err_g1; |
|
- | 335 | ||
- | 336 | pci_set_master(pdev); |
|
- | 337 | ||
- | 338 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { |
|
- | 339 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
|
- | 340 | goto err_g2; |
|
- | 341 | } |
|
- | 342 | ||
- | 343 | DRM_DEBUG("\n"); |
|
- | 344 | ||
- | 345 | ||
- | 346 | dev->pdev = pdev; |
|
- | 347 | dev->pci_device = pdev->device; |
|
- | 348 | dev->pci_vendor = pdev->vendor; |
|
- | 349 | ||
- | 350 | #ifdef __alpha__ |
|
- | 351 | dev->hose = pdev->sysdata; |
|
- | 352 | #endif |
|
- | 353 | ||
- | 354 | // mutex_lock(&drm_global_mutex); |
|
- | 355 | ||
- | 356 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { |
|
- | 357 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
|
- | 358 | goto err_g2; |
|
- | 359 | } |
|
- | 360 | ||
- | 361 | #if 0 |
|
- | 362 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
|
- | 363 | pci_set_drvdata(pdev, dev); |
|
- | 364 | ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); |
|
- | 365 | if (ret) |
|
- | 366 | goto err_g2; |
|
- | 367 | } |
|
- | 368 | ||
- | 369 | if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { |
|
- | 370 | ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER); |
|
- | 371 | if (ret) |
|
- | 372 | goto err_g21; |
|
- | 373 | } |
|
- | 374 | ||
- | 375 | if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) |
|
- | 376 | goto err_g3; |
|
- | 377 | #endif |
|
- | 378 | ||
- | 379 | if (dev->driver->load) { |
|
- | 380 | ret = dev->driver->load(dev, ent->driver_data); |
|
- | 381 | if (ret) |
|
- | 382 | goto err_g4; |
|
- | 383 | } |
|
- | 384 | ||
- | 385 | if (dev->driver->open) { |
|
- | 386 | ret = dev->driver->open(dev, priv); |
|
- | 387 | if (ret < 0) |
|
- | 388 | goto err_g4; |
|
- | 389 | } |
|
- | 390 | ||
- | 391 | ||
- | 392 | // mutex_unlock(&drm_global_mutex); |
|
- | 393 | return 0; |
|
- | 394 | ||
- | 395 | err_g4: |
|
- | 396 | // drm_put_minor(&dev->primary); |
|
- | 397 | err_g3: |
|
- | 398 | // if (dev->render) |
|
- | 399 | // drm_put_minor(&dev->render); |
|
- | 400 | err_g21: |
|
- | 401 | // if (drm_core_check_feature(dev, DRIVER_MODESET)) |
|
- | 402 | // drm_put_minor(&dev->control); |
|
- | 403 | err_g2: |
|
- | 404 | // pci_disable_device(pdev); |
|
- | 405 | err_g1: |
|
- | 406 | // kfree(dev); |
|
- | 407 | // mutex_unlock(&drm_global_mutex); |
|
- | 408 | return ret; |
|
Line 85... | Line 409... | ||
85 | } |
409 | } |
86 | 410 | EXPORT_SYMBOL(drm_get_pci_dev); |
|
87 | 411 | ||
88 | int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) |
412 | int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) |