mesa-drm/linux-core/xgi_misc.c
Ian Romanick 76ca1e858f Convert occurances of U32 to other types.
Most occurances of U32 were converted to u32.  These are cases where
the data represents something that will be written to the hardware.
Other cases were converted to 'unsigned int'.

U32 was the last type in xgi_types.h, so that file is removed.
2007-07-09 18:54:25 -07:00

571 lines
13 KiB
C

/****************************************************************************
* Copyright (C) 2003-2006 by XGI Technology, Taiwan.
* *
* All Rights Reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation on the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* *
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL XGI AND/OR
* ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
***************************************************************************/
#include "xgi_linux.h"
#include "xgi_drv.h"
#include "xgi_regs.h"
#include "xgi_pcie.h"
void xgi_get_device_info(struct xgi_info * info, struct xgi_chip_info * req)
{
req->device_id = info->dev->device;
req->device_name[0] = 'x';
req->device_name[1] = 'g';
req->device_name[2] = '4';
req->device_name[3] = '7';
req->vendor_id = info->dev->vendor;
req->curr_display_mode = 0;
req->fb_size = info->fb.size;
req->sarea_bus_addr = info->sarea_info.bus_addr;
req->sarea_size = info->sarea_info.size;
}
void xgi_get_mmio_info(struct xgi_info * info, struct xgi_mmio_info * req)
{
req->mmio_base = info->mmio.base;
req->size = info->mmio.size;
}
void xgi_put_screen_info(struct xgi_info * info, struct xgi_screen_info * req)
{
info->scrn_info.scrn_start = req->scrn_start;
info->scrn_info.scrn_xres = req->scrn_xres;
info->scrn_info.scrn_yres = req->scrn_yres;
info->scrn_info.scrn_bpp = req->scrn_bpp;
info->scrn_info.scrn_pitch = req->scrn_pitch;
XGI_INFO("info->scrn_info.scrn_start: 0x%lx"
"info->scrn_info.scrn_xres: 0x%lx"
"info->scrn_info.scrn_yres: 0x%lx"
"info->scrn_info.scrn_bpp: 0x%lx"
"info->scrn_info.scrn_pitch: 0x%lx\n",
info->scrn_info.scrn_start,
info->scrn_info.scrn_xres,
info->scrn_info.scrn_yres,
info->scrn_info.scrn_bpp, info->scrn_info.scrn_pitch);
}
void xgi_get_screen_info(struct xgi_info * info, struct xgi_screen_info * req)
{
req->scrn_start = info->scrn_info.scrn_start;
req->scrn_xres = info->scrn_info.scrn_xres;
req->scrn_yres = info->scrn_info.scrn_yres;
req->scrn_bpp = info->scrn_info.scrn_bpp;
req->scrn_pitch = info->scrn_info.scrn_pitch;
XGI_INFO("req->scrn_start: 0x%lx"
"req->scrn_xres: 0x%lx"
"req->scrn_yres: 0x%lx"
"req->scrn_bpp: 0x%lx"
"req->scrn_pitch: 0x%lx\n",
req->scrn_start,
req->scrn_xres,
req->scrn_yres, req->scrn_bpp, req->scrn_pitch);
}
void xgi_ge_reset(struct xgi_info * info)
{
xgi_disable_ge(info);
xgi_enable_ge(info);
}
void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req)
{
info->sarea_info.bus_addr = req->bus_addr;
info->sarea_info.size = req->size;
XGI_INFO("info->sarea_info.bus_addr: 0x%lx"
"info->sarea_info.size: 0x%lx\n",
info->sarea_info.bus_addr, info->sarea_info.size);
}
/*
* irq functions
*/
#define STALL_INTERRUPT_RESET_THRESHOLD 0xffff
static unsigned int s_invalid_begin = 0;
static bool xgi_validate_signal(volatile u8 *mmio_vbase)
{
volatile u32 *const ge_3d_status =
(volatile u32 *)(mmio_vbase + 0x2800);
const u32 old_ge_status = ge_3d_status[0x00];
if (old_ge_status & 0x001c0000) {
u16 check;
/* Check Read back status */
*(mmio_vbase + 0x235c) = 0x80;
check = *((volatile u16 *)(mmio_vbase + 0x2360));
if ((check & 0x3f) != ((check & 0x3f00) >> 8)) {
return FALSE;
}
/* Check RO channel */
*(mmio_vbase + 0x235c) = 0x83;
check = *((volatile u16 *)(mmio_vbase + 0x2360));
if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
return FALSE;
}
/* Check RW channel */
*(mmio_vbase + 0x235c) = 0x88;
check = *((volatile u16 *)(mmio_vbase + 0x2360));
if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
return FALSE;
}
/* Check RO channel outstanding */
*(mmio_vbase + 0x235c) = 0x8f;
check = *((volatile u16 *)(mmio_vbase + 0x2360));
if (0 != (check & 0x3ff)) {
return FALSE;
}
/* Check RW channel outstanding */
*(mmio_vbase + 0x235c) = 0x90;
check = *((volatile u16 *)(mmio_vbase + 0x2360));
if (0 != (check & 0x3ff)) {
return FALSE;
}
/* No pending PCIE request. GE stall. */
}
return TRUE;
}
static void xgi_ge_hang_reset(volatile u8 *mmio_vbase)
{
volatile u32 *const ge_3d_status =
(volatile u32 *)(mmio_vbase + 0x2800);
int time_out = 0xffff;
*(mmio_vbase + 0xb057) = 8;
while (0 != (ge_3d_status[0x00] & 0xf0000000)) {
while (0 != ((--time_out) & 0xfff))
/* empty */ ;
if (0 == time_out) {
u8 old_3ce;
u8 old_3cf;
u8 old_index;
u8 old_36;
XGI_INFO("Can not reset back 0x%x!\n",
ge_3d_status[0x00]);
*(mmio_vbase + 0xb057) = 0;
/* Have to use 3x5.36 to reset. */
/* Save and close dynamic gating */
old_3ce = *(mmio_vbase + 0x3ce);
*(mmio_vbase + 0x3ce) = 0x2a;
old_3cf = *(mmio_vbase + 0x3cf);
*(mmio_vbase + 0x3cf) = old_3cf & 0xfe;
/* Reset GE */
old_index = *(mmio_vbase + 0x3d4);
*(mmio_vbase + 0x3d4) = 0x36;
old_36 = *(mmio_vbase + 0x3d5);
*(mmio_vbase + 0x3d5) = old_36 | 0x10;
while (0 != ((--time_out) & 0xfff))
/* empty */ ;
*(mmio_vbase + 0x3d5) = old_36;
*(mmio_vbase + 0x3d4) = old_index;
/* Restore dynamic gating */
*(mmio_vbase + 0x3cf) = old_3cf;
*(mmio_vbase + 0x3ce) = old_3ce;
break;
}
}
*(mmio_vbase + 0xb057) = 0;
}
bool xgi_ge_irq_handler(struct xgi_info * info)
{
volatile u8 *const mmio_vbase = info->mmio.vbase;
volatile u32 *const ge_3d_status =
(volatile u32 *)(mmio_vbase + 0x2800);
const u32 int_status = ge_3d_status[4];
bool is_support_auto_reset = FALSE;
/* Check GE on/off */
if (0 == (0xffffc0f0 & int_status)) {
u32 old_pcie_cmd_fetch_Addr = ge_3d_status[0x0a];
if (0 != (0x1000 & int_status)) {
/* We got GE stall interrupt.
*/
ge_3d_status[0x04] = int_status | 0x04000000;
if (is_support_auto_reset) {
static cycles_t last_tick;
static unsigned continue_int_count = 0;
/* OE II is busy. */
if (!xgi_validate_signal(mmio_vbase)) {
/* Nothing but skip. */
} else if (0 == continue_int_count++) {
last_tick = get_cycles();
} else {
const cycles_t new_tick = get_cycles();
if ((new_tick - last_tick) >
STALL_INTERRUPT_RESET_THRESHOLD) {
continue_int_count = 0;
} else if (continue_int_count >= 3) {
continue_int_count = 0;
/* GE Hung up, need reset. */
XGI_INFO("Reset GE!\n");
xgi_ge_hang_reset(mmio_vbase);
}
}
}
} else if (0 != (0x1 & int_status)) {
s_invalid_begin++;
ge_3d_status[0x04] = (int_status & ~0x01) | 0x04000000;
}
return TRUE;
}
return FALSE;
}
bool xgi_crt_irq_handler(struct xgi_info * info)
{
bool ret = FALSE;
u8 save_3ce = bReadReg(0x3ce);
if (bIn3cf(0x37) & 0x01) // CRT1 interrupt just happened
{
u8 op3cf_3d;
u8 op3cf_37;
// What happened?
op3cf_37 = bIn3cf(0x37);
// Clear CRT interrupt
op3cf_3d = bIn3cf(0x3d);
bOut3cf(0x3d, (op3cf_3d | 0x04));
bOut3cf(0x3d, (op3cf_3d & ~0x04));
ret = TRUE;
}
bWriteReg(0x3ce, save_3ce);
return (ret);
}
bool xgi_dvi_irq_handler(struct xgi_info * info)
{
bool ret = FALSE;
u8 save_3ce = bReadReg(0x3ce);
if (bIn3cf(0x38) & 0x20) // DVI interrupt just happened
{
u8 op3cf_39;
u8 op3cf_37;
u8 op3x5_5a;
u8 save_3x4 = bReadReg(0x3d4);;
// What happened?
op3cf_37 = bIn3cf(0x37);
//Notify BIOS that DVI plug/unplug happened
op3x5_5a = bIn3x5(0x5a);
bOut3x5(0x5a, op3x5_5a & 0xf7);
bWriteReg(0x3d4, save_3x4);
// Clear DVI interrupt
op3cf_39 = bIn3cf(0x39);
bOut3c5(0x39, (op3cf_39 & ~0x01)); //Set 3cf.39 bit 0 to 0
bOut3c5(0x39, (op3cf_39 | 0x01)); //Set 3cf.39 bit 0 to 1
ret = TRUE;
}
bWriteReg(0x3ce, save_3ce);
return (ret);
}
void xgi_dump_register(struct xgi_info * info)
{
int i, j;
unsigned char temp;
// 0x3C5
printk("\r\n=====xgi_dump_register========0x%x===============\r\n",
0x3C5);
for (i = 0; i < 0x10; i++) {
if (i == 0) {
printk("%5x", i);
} else {
printk("%3x", i);
}
}
printk("\r\n");
for (i = 0; i < 0x10; i++) {
printk("%1x ", i);
for (j = 0; j < 0x10; j++) {
temp = bIn3c5(i * 0x10 + j);
printk("%3x", temp);
}
printk("\r\n");
}
// 0x3D5
printk("\r\n====xgi_dump_register=========0x%x===============\r\n",
0x3D5);
for (i = 0; i < 0x10; i++) {
if (i == 0) {
printk("%5x", i);
} else {
printk("%3x", i);
}
}
printk("\r\n");
for (i = 0; i < 0x10; i++) {
printk("%1x ", i);
for (j = 0; j < 0x10; j++) {
temp = bIn3x5(i * 0x10 + j);
printk("%3x", temp);
}
printk("\r\n");
}
// 0x3CF
printk("\r\n=========xgi_dump_register====0x%x===============\r\n",
0x3CF);
for (i = 0; i < 0x10; i++) {
if (i == 0) {
printk("%5x", i);
} else {
printk("%3x", i);
}
}
printk("\r\n");
for (i = 0; i < 0x10; i++) {
printk("%1x ", i);
for (j = 0; j < 0x10; j++) {
temp = bIn3cf(i * 0x10 + j);
printk("%3x", temp);
}
printk("\r\n");
}
printk("\r\n=====xgi_dump_register======0x%x===============\r\n",
0xB000);
for (i = 0; i < 0x10; i++) {
if (i == 0) {
printk("%5x", i);
} else {
printk("%3x", i);
}
}
printk("\r\n");
for (i = 0; i < 0x5; i++) {
printk("%1x ", i);
for (j = 0; j < 0x10; j++) {
temp = bReadReg(0xB000 + i * 0x10 + j);
printk("%3x", temp);
}
printk("\r\n");
}
printk("\r\n==================0x%x===============\r\n", 0x2200);
for (i = 0; i < 0x10; i++) {
if (i == 0) {
printk("%5x", i);
} else {
printk("%3x", i);
}
}
printk("\r\n");
for (i = 0; i < 0xB; i++) {
printk("%1x ", i);
for (j = 0; j < 0x10; j++) {
temp = bReadReg(0x2200 + i * 0x10 + j);
printk("%3x", temp);
}
printk("\r\n");
}
printk("\r\n==================0x%x===============\r\n", 0x2300);
for (i = 0; i < 0x10; i++) {
if (i == 0) {
printk("%5x", i);
} else {
printk("%3x", i);
}
}
printk("\r\n");
for (i = 0; i < 0x7; i++) {
printk("%1x ", i);
for (j = 0; j < 0x10; j++) {
temp = bReadReg(0x2300 + i * 0x10 + j);
printk("%3x", temp);
}
printk("\r\n");
}
printk("\r\n==================0x%x===============\r\n", 0x2400);
for (i = 0; i < 0x10; i++) {
if (i == 0) {
printk("%5x", i);
} else {
printk("%3x", i);
}
}
printk("\r\n");
for (i = 0; i < 0x10; i++) {
printk("%1x ", i);
for (j = 0; j < 0x10; j++) {
temp = bReadReg(0x2400 + i * 0x10 + j);
printk("%3x", temp);
}
printk("\r\n");
}
printk("\r\n==================0x%x===============\r\n", 0x2800);
for (i = 0; i < 0x10; i++) {
if (i == 0) {
printk("%5x", i);
} else {
printk("%3x", i);
}
}
printk("\r\n");
for (i = 0; i < 0x10; i++) {
printk("%1x ", i);
for (j = 0; j < 0x10; j++) {
temp = bReadReg(0x2800 + i * 0x10 + j);
printk("%3x", temp);
}
printk("\r\n");
}
}
void xgi_restore_registers(struct xgi_info * info)
{
bOut3x5(0x13, 0);
bOut3x5(0x8b, 2);
}
void xgi_waitfor_pci_idle(struct xgi_info * info)
{
#define WHOLD_GE_STATUS 0x2800
#define IDLE_MASK ~0x90200000
int idleCount = 0;
while (idleCount < 5) {
if (dwReadReg(WHOLD_GE_STATUS) & IDLE_MASK) {
idleCount = 0;
} else {
idleCount++;
}
}
}
/*memory collect function*/
extern struct list_head xgi_mempid_list;
void xgi_mem_collect(struct xgi_info * info, unsigned int *pcnt)
{
struct xgi_mem_pid *block;
struct xgi_mem_pid *next;
struct task_struct *p, *find;
unsigned int cnt = 0;
list_for_each_entry_safe(block, next, &xgi_mempid_list, list) {
find = NULL;
XGI_SCAN_PROCESS(p) {
if (p->pid == block->pid) {
XGI_INFO
("[!]Find active pid:%ld state:%ld location:%d addr:0x%lx! \n",
block->pid, p->state,
block->location,
block->bus_addr);
find = p;
if (block->bus_addr == 0xFFFFFFFF)
++cnt;
break;
}
}
if (!find) {
if (block->location == XGI_MEMLOC_LOCAL) {
XGI_INFO
("Memory ProcessID free fb and delete one block pid:%ld addr:0x%lx successfully! \n",
block->pid, block->bus_addr);
xgi_fb_free(info, block->bus_addr);
} else if (block->bus_addr != 0xFFFFFFFF) {
XGI_INFO
("Memory ProcessID free pcie and delete one block pid:%ld addr:0x%lx successfully! \n",
block->pid, block->bus_addr);
xgi_pcie_free(info, block->bus_addr);
} else {
/*only delete the memory block */
list_del(&block->list);
XGI_INFO
("Memory ProcessID delete one pcie block pid:%ld successfully! \n",
block->pid);
kfree(block);
}
}
}
*pcnt = cnt;
}