#include <sys/libkern.h>
#include <sys/ctype.h>
#include <drm/drmP.h>
int
fb_get_options(const char *connector_name, char **option)
{
char buf[128], str[1024];
memset(str, 0, sizeof(str));
ksnprintf(buf, sizeof(buf), "drm.video.%s", connector_name);
if (kgetenv_string(buf, str, sizeof(str)-1)) {
kprintf("found kenv %s=%s\n", buf, str);
*option = kstrdup(str, M_DRM);
return (0);
} else {
kprintf("tunable %s is not set\n", buf);
return (1);
}
}
char *kvasprintf(int flags, const char *format, va_list ap)
{
char *str;
size_t size;
va_list aq;
va_copy(aq, ap);
size = kvsnprintf(NULL, 0, format, aq);
va_end(aq);
str = kmalloc(size+1, M_DRM, flags);
if (str == NULL)
return NULL;
kvsnprintf(str, size+1, format, ap);
return str;
}
char *kasprintf(int flags, const char *format, ...)
{
char *str;
va_list ap;
va_start(ap, format);
str = kvasprintf(flags, format, ap);
va_end(ap);
return str;
}
static void drm_fill_pdev(device_t dev, struct pci_dev *pdev)
{
int msi_enable = 1;
u_int irq_flags;
int slot, func;
pdev->dev.bsddev = dev;
pdev->devfn = PCI_DEVFN(pci_get_slot(dev), pci_get_function(dev));
pdev->vendor = pci_get_vendor(dev);
pdev->device = pci_get_device(dev);
pdev->subsystem_vendor = pci_get_subvendor(dev);
pdev->subsystem_device = pci_get_subdevice(dev);
pdev->revision = pci_get_revid(dev) & 0xff;
pdev->_irq_type = pci_alloc_1intr(dev, msi_enable,
&pdev->_irqrid, &irq_flags);
pdev->_irqr = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&pdev->_irqrid, irq_flags);
if (!pdev->_irqr)
return;
pdev->irq = (int)rman_get_start(pdev->_irqr);
slot = pci_get_slot(dev);
func = pci_get_function(dev);
pdev->devfn = PCI_DEVFN(slot, func);
}
void drm_init_pdev(device_t dev, struct pci_dev **pdev)
{
BUG_ON(*pdev != NULL);
*pdev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
drm_fill_pdev(dev, *pdev);
(*pdev)->bus = kzalloc(sizeof(struct pci_bus), GFP_KERNEL);
(*pdev)->bus->self = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
drm_fill_pdev(device_get_parent(dev), (*pdev)->bus->self);
(*pdev)->bus->number = pci_get_bus(dev);
}
static void
drm_release_pdev_irq(struct pci_dev *pdev)
{
if (pdev->_irqr != NULL) {
bus_release_resource(pdev->dev.bsddev, SYS_RES_IRQ,
pdev->_irqrid, pdev->_irqr);
pdev->_irqr = NULL;
}
if (pdev->_irq_type == PCI_INTR_TYPE_MSI) {
pci_release_msi(pdev->dev.bsddev);
pdev->_irq_type = 0;
}
}
void drm_fini_pdev(struct pci_dev **pdev)
{
if (*pdev == NULL)
return;
drm_release_pdev_irq((*pdev)->bus->self);
kfree((*pdev)->bus->self);
kfree((*pdev)->bus);
drm_release_pdev_irq(*pdev);
kfree(*pdev);
*pdev = NULL;
}
void drm_print_pdev(struct pci_dev *pdev)
{
if (pdev == NULL) {
DRM_ERROR("pdev is null!\n");
return;
}
DRM_INFO("pdev: vendor=0x%04x device=0x%04x rev=0x%02x\n",
pdev->vendor, pdev->device, pdev->revision);
DRM_INFO(" svendor=0x%04x sdevice=0x%04x irq=%u\n",
pdev->subsystem_vendor, pdev->subsystem_device, pdev->irq);
}
#if 0
static int drm_alloc_resource(struct drm_device *dev, int resource)
{
struct resource *res;
int rid;
KKASSERT(lockowned(&dev->struct_mutex));
if (resource >= DRM_MAX_PCI_RESOURCE) {
DRM_ERROR("Resource %d too large\n", resource);
return 1;
}
if (dev->pcir[resource] != NULL) {
return 0;
}
DRM_UNLOCK(dev);
rid = PCIR_BAR(resource);
res = bus_alloc_resource_any(dev->dev->bsddev, SYS_RES_MEMORY, &rid,
RF_SHAREABLE);
DRM_LOCK(dev);
if (res == NULL) {
DRM_ERROR("Couldn't find resource 0x%x\n", resource);
DRM_UNLOCK(dev);
return 1;
}
if (dev->pcir[resource] == NULL) {
dev->pcirid[resource] = rid;
dev->pcir[resource] = res;
}
return 0;
}
unsigned long drm_get_resource_start(struct drm_device *dev,
unsigned int resource)
{
if (drm_alloc_resource(dev, resource) != 0)
return 0;
return rman_get_start(dev->pcir[resource]);
}
unsigned long drm_get_resource_len(struct drm_device *dev,
unsigned int resource)
{
if (drm_alloc_resource(dev, resource) != 0)
return 0;
return rman_get_size(dev->pcir[resource]);
}
#endif
int drm_device_detach(device_t kdev)
{
struct drm_softc *softc = device_get_softc(kdev);
struct drm_device *dev = softc->drm_driver_data;
drm_sysctl_cleanup(dev);
#ifdef __DragonFly__
#if 0
for (int i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
if (dev->pcir[i] == NULL)
continue;
bus_release_resource(dev->dev->bsddev, SYS_RES_MEMORY,
dev->pcirid[i], dev->pcir[i]);
dev->pcir[i] = NULL;
}
#endif
if (dev->agp) {
kfree(dev->agp);
dev->agp = NULL;
}
if (dev->driver->unload != NULL) {
DRM_LOCK(dev);
dev->driver->unload(dev);
DRM_UNLOCK(dev);
}
if (pci_disable_busmaster(dev->dev->bsddev))
DRM_ERROR("Request to disable bus-master failed.\n");
lockuninit(&dev->vbl_lock);
lockuninit(&dev->event_lock);
lockuninit(&dev->struct_mutex);
#endif
drm_fini_pdev(&dev->pdev);
return 0;
}