radeon_drv.c revision 1450
1450N/A/*
1450N/A * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
1450N/A */
1450N/A
1450N/A/*
1450N/A * radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
1450N/A * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
1450N/A */
1450N/A/*
1450N/A * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
1450N/A * All Rights Reserved.
1450N/A *
1450N/A * Permission is hereby granted, free of charge, to any person obtaining a
1450N/A * copy of this software and associated documentation files (the "Software"),
1450N/A * to deal in the Software without restriction, including without limitation
1450N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1450N/A * and/or sell copies of the Software, and to permit persons to whom the
1450N/A * Software is furnished to do so, subject to the following conditions:
1450N/A *
1450N/A * The above copyright notice and this permission notice (including the next
1450N/A * paragraph) shall be included in all copies or substantial portions of the
1450N/A * Software.
1450N/A *
1450N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1450N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1450N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1450N/A * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
1450N/A * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1450N/A * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1450N/A * OTHER DEALINGS IN THE SOFTWARE.
1450N/A *
1450N/A * Authors:
1450N/A * Gareth Hughes <gareth@valinux.com>
1450N/A *
1450N/A */
1450N/A
1450N/A#include "drmP.h"
1450N/A#include "drm.h"
1450N/A#include "radeon_drm.h"
1450N/A#include "radeon_drv.h"
1450N/A#include "drm_pciids.h"
1450N/A
1450N/A#ifdef __sparc
1450N/A#include "efb.h"
1450N/A#endif /* sparc */
1450N/A
1450N/Aint radeon_no_wb = 1;
1450N/A
1450N/A/*
1450N/A * cb_ops entrypoint
1450N/A */
1450N/Aextern struct cb_ops drm_cb_ops;
1450N/A
1450N/A/* drv_PCI_IDs comes from drm_pciids.h */
1450N/Astatic const drm_pci_id_list_t radeon_pciidlist[] = {
1450N/A radeon_PCI_IDS
1450N/A};
1450N/A
1450N/A/*
1450N/A * module entrypoint
1450N/A */
1450N/Astatic int radeon_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
1450N/Astatic int radeon_attach(dev_info_t *, ddi_attach_cmd_t);
1450N/Astatic int radeon_detach(dev_info_t *, ddi_detach_cmd_t);
1450N/A
1450N/Aextern void radeon_init_ioctl_arrays(void);
1450N/Aextern uint_t radeon_driver_irq_handler(caddr_t);
1450N/Aextern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *);
1450N/A
1450N/A/*
1450N/A * Local routines
1450N/A */
1450N/Astatic void radeon_configure(drm_driver_t *);
1450N/A
1450N/A/*
1450N/A * DRM driver
1450N/A */
1450N/Astatic drm_driver_t radeon_driver = {0};
1450N/A
1450N/A/*
1450N/A * Common device operations structure for all DRM drivers
1450N/A */
1450N/A
1450N/A#ifdef __sparc
1450N/Astatic struct cb_ops efb_cb_ops = {
1450N/A nodev, /* cb_open */
1450N/A nodev, /* cb_close */
1450N/A nodev, /* cb_strategy */
1450N/A nodev, /* cb_print */
1450N/A nodev, /* cb_dump */
1450N/A nodev, /* cb_read */
1450N/A nodev, /* cb_write */
1450N/A efb_ioctl, /* cb_ioctl */
1450N/A nodev, /* cb_devmap */
1450N/A nodev, /* cb_mmap */
1450N/A NULL, /* cb_segmap */
1450N/A nochpoll, /* cb_chpoll */
1450N/A ddi_prop_op, /* cb_prop_op */
1450N/A 0, /* cb_stream */
1450N/A D_NEW | D_MTSAFE |D_DEVMAP /* cb_flag */
1450N/A};
1450N/A
1450N/Astatic struct dev_ops efb_dev_ops = {
1450N/A DEVO_REV, /* devo_rev */
1450N/A 0, /* devo_refcnt */
1450N/A radeon_info, /* devo_getinfo */
1450N/A nulldev, /* devo_identify */
1450N/A nulldev, /* devo_probe */
1450N/A radeon_attach, /* devo_attach */
1450N/A radeon_detach, /* devo_detach */
1450N/A nodev, /* devo_reset */
1450N/A &efb_cb_ops, /* devo_cb_ops */
1450N/A NULL, /* devo_bus_ops */
1450N/A NULL /* power */
1450N/A};
1450N/A
1450N/Astatic struct modldrv modldrv = {
1450N/A &mod_driverops, /* drv_modops */
1450N/A "efb DRM driver 1.4", /* drv_linkinfo */
1450N/A &efb_dev_ops, /* drv_dev_ops */
1450N/A};
1450N/A
1450N/A#else
1450N/A
1450N/Astatic struct dev_ops radeon_dev_ops = {
1450N/A DEVO_REV, /* devo_rev */
1450N/A 0, /* devo_refcnt */
1450N/A radeon_info, /* devo_getinfo */
1450N/A nulldev, /* devo_identify */
1450N/A nulldev, /* devo_probe */
1450N/A radeon_attach, /* devo_attach */
1450N/A radeon_detach, /* devo_detach */
1450N/A nodev, /* devo_reset */
1450N/A &drm_cb_ops, /* devo_cb_ops */
1450N/A NULL, /* devo_bus_ops */
1450N/A NULL /* power */
1450N/A};
1450N/A
1450N/Astatic struct modldrv modldrv = {
1450N/A &mod_driverops, /* drv_modops */
1450N/A "radeon DRM driver 1.4", /* drv_linkinfo */
1450N/A &radeon_dev_ops, /* drv_dev_ops */
1450N/A};
1450N/A#endif
1450N/A
1450N/Astatic struct modlinkage modlinkage = {
1450N/A MODREV_1, (void *) &modldrv, NULL
1450N/A};
1450N/A
1450N/A
1450N/A/*
1450N/A * softstate head
1450N/A */
1450N/Avoid *radeon_statep;
1450N/A
1450N/Aint
1450N/A_init(void)
1450N/A{
1450N/A int error;
1450N/A
1450N/A radeon_configure(&radeon_driver);
1450N/A
1450N/A if ((error = ddi_soft_state_init(&radeon_statep,
1450N/A sizeof (drm_device_t), DRM_MAX_INSTANCES)) != 0)
1450N/A return (error);
1450N/A
1450N/A#ifdef __sparc
1450N/A efb_init(radeon_statep, &efb_cb_ops, &radeon_driver);
1450N/A#endif /* sparc */
1450N/A
1450N/A if ((error = mod_install(&modlinkage)) != 0) {
1450N/A ddi_soft_state_fini(&radeon_statep);
1450N/A return (error);
1450N/A }
1450N/A
1450N/A return (error);
1450N/A
1450N/A} /* _init() */
1450N/A
1450N/Aint
1450N/A_fini(void)
1450N/A{
1450N/A int error;
1450N/A
1450N/A if ((error = mod_remove(&modlinkage)) != 0)
1450N/A return (error);
1450N/A
1450N/A (void) ddi_soft_state_fini(&radeon_statep);
1450N/A
1450N/A return (0);
1450N/A
1450N/A} /* _fini() */
1450N/A
1450N/Aint
1450N/A_info(struct modinfo *modinfop)
1450N/A{
1450N/A return (mod_info(&modlinkage, modinfop));
1450N/A
1450N/A} /* _info() */
1450N/A
1450N/A
1450N/Astatic int
1450N/Aradeon_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1450N/A{
1450N/A drm_device_t *statep;
1450N/A
1450N/A void *handle;
1450N/A int unit;
1450N/A
1450N/A if (cmd != DDI_ATTACH) {
1450N/A DRM_ERROR("radeon_attach: only attach op supported");
1450N/A return (DDI_FAILURE);
1450N/A }
1450N/A
1450N/A unit = ddi_get_instance(dip);
1450N/A if (ddi_soft_state_zalloc(radeon_statep, unit) != DDI_SUCCESS) {
1450N/A cmn_err(CE_WARN,
1450N/A "radeon_attach: alloc softstate failed unit=%d", unit);
1450N/A return (DDI_FAILURE);
1450N/A }
1450N/A statep = ddi_get_soft_state(radeon_statep, unit);
1450N/A
1450N/A statep->dip = dip;
1450N/A statep->driver = &radeon_driver;
1450N/A
1450N/A /*
1450N/A * Call drm_supp_register to create minor nodes for us
1450N/A */
1450N/A handle = drm_supp_register(dip, statep);
1450N/A if (handle == NULL) {
1450N/A DRM_ERROR("radeon_attach: drm_supp_register failed");
1450N/A goto err_exit1;
1450N/A }
1450N/A statep->drm_handle = handle;
1450N/A
1450N/A
1450N/A /*
1450N/A * After drm_supp_register, we can call drm_xxx routine
1450N/A */
1450N/A statep->drm_supported = DRM_UNSUPPORT;
1450N/A if (drm_probe(statep, radeon_pciidlist) != DDI_SUCCESS) {
1450N/A DRM_ERROR("radeon_open: "
1450N/A "DRM current don't support this graphics card");
1450N/A goto err_exit2;
1450N/A }
1450N/A statep->drm_supported = DRM_SUPPORT;
1450N/A
1450N/A /* call common attach code */
1450N/A if (drm_attach(statep) != DDI_SUCCESS) {
1450N/A DRM_ERROR("radeon_attach: drm_attach failed");
1450N/A goto err_exit2;
1450N/A }
1450N/A
1450N/A#ifdef __sparc
1450N/A if (efb_attach(statep) != DDI_SUCCESS) {
1450N/A goto err_exit2;
1450N/A }
1450N/A#endif /* sparc */
1450N/A
1450N/A return (DDI_SUCCESS);
1450N/A
1450N/Aerr_exit2:
1450N/A (void) drm_supp_unregister(handle);
1450N/Aerr_exit1:
1450N/A (void) ddi_soft_state_free(radeon_statep, unit);
1450N/A return (DDI_FAILURE);
1450N/A
1450N/A} /* radeon_attach() */
1450N/A
1450N/Astatic int
1450N/Aradeon_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1450N/A{
1450N/A drm_device_t *statep;
1450N/A int unit;
1450N/A
1450N/A if (cmd != DDI_DETACH)
1450N/A return (DDI_FAILURE);
1450N/A
1450N/A unit = ddi_get_instance(dip);
1450N/A statep = ddi_get_soft_state(radeon_statep, unit);
1450N/A if (statep == NULL)
1450N/A return (DDI_FAILURE);
1450N/A
1450N/A#ifdef __sparc
1450N/A (void) efb_detach(statep);
1450N/A#endif /* sparc */
1450N/A
1450N/A (void) drm_detach(statep);
1450N/A (void) drm_supp_unregister(statep->drm_handle);
1450N/A (void) ddi_soft_state_free(radeon_statep, unit);
1450N/A
1450N/A return (DDI_SUCCESS);
1450N/A
1450N/A} /* radeon_detach() */
1450N/A
1450N/A/*ARGSUSED*/
1450N/Astatic int
1450N/Aradeon_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
1450N/A{
1450N/A drm_device_t *statep;
1450N/A int error = DDI_SUCCESS;
1450N/A int unit;
1450N/A
1450N/A unit = drm_dev_to_instance((dev_t)arg);
1450N/A switch (infocmd) {
1450N/A case DDI_INFO_DEVT2DEVINFO:
1450N/A statep = ddi_get_soft_state(radeon_statep, unit);
1450N/A if (statep == NULL || statep->dip == NULL) {
1450N/A error = DDI_FAILURE;
1450N/A } else {
1450N/A *result = (void *) statep->dip;
1450N/A error = DDI_SUCCESS;
1450N/A }
1450N/A break;
1450N/A case DDI_INFO_DEVT2INSTANCE:
1450N/A *result = (void *)(uintptr_t)unit;
1450N/A error = DDI_SUCCESS;
1450N/A break;
1450N/A default:
1450N/A error = DDI_FAILURE;
1450N/A break;
1450N/A }
1450N/A return (error);
1450N/A
1450N/A} /* radeon_info() */
1450N/A
1450N/Astatic void
1450N/Aradeon_configure(drm_driver_t *driver)
1450N/A{
1450N/A driver->buf_priv_size = sizeof (drm_radeon_buf_priv_t);
1450N/A driver->load = radeon_driver_load;
1450N/A driver->unload = radeon_driver_unload;
1450N/A driver->firstopen = radeon_driver_firstopen;
1450N/A driver->open = radeon_driver_open;
1450N/A driver->preclose = radeon_driver_preclose;
1450N/A driver->postclose = radeon_driver_postclose;
1450N/A driver->lastclose = radeon_driver_lastclose;
1450N/A driver->vblank_wait = radeon_driver_vblank_wait;
1450N/A driver->vblank_wait2 = radeon_driver_vblank_wait2;
1450N/A driver->irq_preinstall = radeon_driver_irq_preinstall;
1450N/A driver->irq_postinstall = radeon_driver_irq_postinstall;
1450N/A driver->irq_uninstall = radeon_driver_irq_uninstall;
1450N/A driver->irq_handler = radeon_driver_irq_handler;
1450N/A driver->dma_ioctl = radeon_cp_buffers;
1450N/A
1450N/A driver->driver_ioctls = radeon_ioctls;
1450N/A driver->max_driver_ioctl = radeon_max_ioctl;
1450N/A
1450N/A driver->driver_name = DRIVER_NAME;
1450N/A driver->driver_desc = DRIVER_DESC;
1450N/A driver->driver_date = DRIVER_DATE;
1450N/A driver->driver_major = DRIVER_MAJOR;
1450N/A driver->driver_minor = DRIVER_MINOR;
1450N/A driver->driver_patchlevel = DRIVER_PATCHLEVEL;
1450N/A
1450N/A driver->use_agp = 1;
1450N/A driver->use_mtrr = 1;
1450N/A driver->use_pci_dma = 1;
1450N/A driver->use_sg = 1;
1450N/A driver->use_dma = 1;
1450N/A driver->use_irq = 1;
1450N/A driver->use_vbl_irq = 1;
1450N/A driver->use_vbl_irq2 = 1;
1450N/A
1450N/A} /* radeon_configure() */