2007-06-26 14:10:30 -06:00
|
|
|
/****************************************************************************
|
2007-07-24 14:36:02 -06:00
|
|
|
* Copyright (C) 2003-2006 by XGI Technology, Taiwan.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
2007-06-26 14:10:30 -06:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
2007-07-24 14:36:02 -06:00
|
|
|
* 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.
|
2007-06-26 14:10:30 -06:00
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "xgi_drv.h"
|
|
|
|
#include "xgi_regs.h"
|
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
#include <linux/delay.h>
|
|
|
|
|
2007-07-27 16:45:59 -06:00
|
|
|
int xgi_ge_reset_ioctl(struct drm_device * dev, void * data,
|
|
|
|
struct drm_file * filp)
|
2007-06-26 14:10:30 -06:00
|
|
|
{
|
2007-07-19 11:29:18 -06:00
|
|
|
struct xgi_info *info = dev->dev_private;
|
|
|
|
|
2007-06-26 14:10:30 -06:00
|
|
|
xgi_disable_ge(info);
|
|
|
|
xgi_enable_ge(info);
|
2007-07-19 11:29:18 -06:00
|
|
|
|
|
|
|
return 0;
|
2007-06-26 14:10:30 -06:00
|
|
|
}
|
|
|
|
|
2007-07-19 11:29:18 -06:00
|
|
|
|
2007-06-26 14:10:30 -06:00
|
|
|
/*
|
|
|
|
* irq functions
|
|
|
|
*/
|
|
|
|
#define STALL_INTERRUPT_RESET_THRESHOLD 0xffff
|
|
|
|
|
2007-06-29 22:48:31 -06:00
|
|
|
static unsigned int s_invalid_begin = 0;
|
2007-06-26 14:10:30 -06:00
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
static bool xgi_validate_signal(struct drm_map * map)
|
2007-07-05 18:45:44 -06:00
|
|
|
{
|
2007-07-30 11:02:46 -06:00
|
|
|
if (DRM_READ32(map, 0x2800) & 0x001c0000) {
|
2007-07-05 18:45:44 -06:00
|
|
|
u16 check;
|
|
|
|
|
|
|
|
/* Check Read back status */
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0x235c, 0x80);
|
|
|
|
check = DRM_READ16(map, 0x2360);
|
2007-07-05 18:45:44 -06:00
|
|
|
|
|
|
|
if ((check & 0x3f) != ((check & 0x3f00) >> 8)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check RO channel */
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0x235c, 0x83);
|
|
|
|
check = DRM_READ16(map, 0x2360);
|
2007-07-05 18:45:44 -06:00
|
|
|
if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check RW channel */
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0x235c, 0x88);
|
|
|
|
check = DRM_READ16(map, 0x2360);
|
2007-07-05 18:45:44 -06:00
|
|
|
if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check RO channel outstanding */
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0x235c, 0x8f);
|
|
|
|
check = DRM_READ16(map, 0x2360);
|
2007-07-05 18:45:44 -06:00
|
|
|
if (0 != (check & 0x3ff)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check RW channel outstanding */
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0x235c, 0x90);
|
|
|
|
check = DRM_READ16(map, 0x2360);
|
2007-07-05 18:45:44 -06:00
|
|
|
if (0 != (check & 0x3ff)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No pending PCIE request. GE stall. */
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
static void xgi_ge_hang_reset(struct drm_map * map)
|
2007-07-05 18:45:44 -06:00
|
|
|
{
|
|
|
|
int time_out = 0xffff;
|
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0xb057, 8);
|
|
|
|
while (0 != (DRM_READ32(map, 0x2800) & 0xf0000000)) {
|
2007-07-05 18:45:44 -06:00
|
|
|
while (0 != ((--time_out) & 0xfff))
|
|
|
|
/* empty */ ;
|
|
|
|
|
|
|
|
if (0 == time_out) {
|
|
|
|
u8 old_3ce;
|
|
|
|
u8 old_3cf;
|
|
|
|
u8 old_index;
|
|
|
|
u8 old_36;
|
|
|
|
|
2007-07-19 11:29:18 -06:00
|
|
|
DRM_INFO("Can not reset back 0x%x!\n",
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_READ32(map, 0x2800));
|
2007-07-05 18:45:44 -06:00
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0xb057, 0);
|
2007-07-05 18:45:44 -06:00
|
|
|
|
|
|
|
/* Have to use 3x5.36 to reset. */
|
|
|
|
/* Save and close dynamic gating */
|
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
old_3ce = DRM_READ8(map, 0x3ce);
|
|
|
|
DRM_WRITE8(map, 0x3ce, 0x2a);
|
|
|
|
old_3cf = DRM_READ8(map, 0x3cf);
|
|
|
|
DRM_WRITE8(map, 0x3cf, old_3cf & 0xfe);
|
2007-07-05 18:45:44 -06:00
|
|
|
|
|
|
|
/* Reset GE */
|
2007-07-30 11:02:46 -06:00
|
|
|
old_index = DRM_READ8(map, 0x3d4);
|
|
|
|
DRM_WRITE8(map, 0x3d4, 0x36);
|
|
|
|
old_36 = DRM_READ8(map, 0x3d5);
|
|
|
|
DRM_WRITE8(map, 0x3d5, old_36 | 0x10);
|
|
|
|
|
2007-07-05 18:45:44 -06:00
|
|
|
while (0 != ((--time_out) & 0xfff))
|
|
|
|
/* empty */ ;
|
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0x3d5, old_36);
|
|
|
|
DRM_WRITE8(map, 0x3d4, old_index);
|
2007-07-05 18:45:44 -06:00
|
|
|
|
|
|
|
/* Restore dynamic gating */
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0x3cf, old_3cf);
|
|
|
|
DRM_WRITE8(map, 0x3ce, old_3ce);
|
2007-07-05 18:45:44 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE8(map, 0xb057, 0);
|
2007-07-05 18:45:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-29 17:37:01 -06:00
|
|
|
bool xgi_ge_irq_handler(struct xgi_info * info)
|
2007-06-26 14:10:30 -06:00
|
|
|
{
|
2007-07-30 11:02:46 -06:00
|
|
|
const u32 int_status = DRM_READ32(info->mmio_map, 0x2810);
|
2007-06-29 17:37:01 -06:00
|
|
|
bool is_support_auto_reset = FALSE;
|
2007-06-26 14:10:30 -06:00
|
|
|
|
2007-07-05 18:45:44 -06:00
|
|
|
/* Check GE on/off */
|
2007-06-26 14:10:30 -06:00
|
|
|
if (0 == (0xffffc0f0 & int_status)) {
|
|
|
|
if (0 != (0x1000 & int_status)) {
|
2007-07-05 18:45:44 -06:00
|
|
|
/* We got GE stall interrupt.
|
|
|
|
*/
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE32(info->mmio_map, 0x2810,
|
|
|
|
int_status | 0x04000000);
|
2007-06-26 14:10:30 -06:00
|
|
|
|
2007-07-05 18:18:12 -06:00
|
|
|
if (is_support_auto_reset) {
|
|
|
|
static cycles_t last_tick;
|
|
|
|
static unsigned continue_int_count = 0;
|
2007-06-26 14:10:30 -06:00
|
|
|
|
2007-07-05 18:45:44 -06:00
|
|
|
/* OE II is busy. */
|
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
if (!xgi_validate_signal(info->mmio_map)) {
|
2007-07-05 18:45:44 -06:00
|
|
|
/* Nothing but skip. */
|
2007-07-05 18:18:12 -06:00
|
|
|
} else if (0 == continue_int_count++) {
|
|
|
|
last_tick = get_cycles();
|
2007-06-26 14:10:30 -06:00
|
|
|
} else {
|
2007-07-05 18:18:12 -06:00
|
|
|
const cycles_t new_tick = get_cycles();
|
|
|
|
if ((new_tick - last_tick) >
|
2007-06-26 14:10:30 -06:00
|
|
|
STALL_INTERRUPT_RESET_THRESHOLD) {
|
2007-07-05 18:18:12 -06:00
|
|
|
continue_int_count = 0;
|
|
|
|
} else if (continue_int_count >= 3) {
|
|
|
|
continue_int_count = 0;
|
2007-06-26 14:10:30 -06:00
|
|
|
|
2007-07-05 18:45:44 -06:00
|
|
|
/* GE Hung up, need reset. */
|
2007-07-19 11:29:18 -06:00
|
|
|
DRM_INFO("Reset GE!\n");
|
2007-06-26 14:10:30 -06:00
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
xgi_ge_hang_reset(info->mmio_map);
|
2007-06-26 14:10:30 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (0 != (0x1 & int_status)) {
|
|
|
|
s_invalid_begin++;
|
2007-07-30 11:02:46 -06:00
|
|
|
DRM_WRITE32(info->mmio_map, 0x2810,
|
|
|
|
(int_status & ~0x01) | 0x04000000);
|
2007-06-26 14:10:30 -06:00
|
|
|
}
|
2007-07-05 18:45:44 -06:00
|
|
|
|
|
|
|
return TRUE;
|
2007-06-26 14:10:30 -06:00
|
|
|
}
|
2007-07-05 18:45:44 -06:00
|
|
|
|
2007-06-26 14:10:30 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-06-29 17:37:01 -06:00
|
|
|
bool xgi_crt_irq_handler(struct xgi_info * info)
|
2007-06-26 14:10:30 -06:00
|
|
|
{
|
2007-06-29 17:37:01 -06:00
|
|
|
bool ret = FALSE;
|
2007-07-19 11:29:18 -06:00
|
|
|
u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
|
2007-06-26 14:10:30 -06:00
|
|
|
|
2007-07-19 11:29:18 -06:00
|
|
|
if (IN3CFB(info->mmio_map, 0x37) & 0x01) // CRT1 interrupt just happened
|
2007-06-26 14:10:30 -06:00
|
|
|
{
|
2007-06-29 17:41:32 -06:00
|
|
|
u8 op3cf_3d;
|
|
|
|
u8 op3cf_37;
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
// What happened?
|
2007-07-19 11:29:18 -06:00
|
|
|
op3cf_37 = IN3CFB(info->mmio_map, 0x37);
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
// Clear CRT interrupt
|
2007-07-19 11:29:18 -06:00
|
|
|
op3cf_3d = IN3CFB(info->mmio_map, 0x3d);
|
|
|
|
OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d | 0x04));
|
|
|
|
OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d & ~0x04));
|
2007-06-26 14:10:30 -06:00
|
|
|
ret = TRUE;
|
|
|
|
}
|
2007-07-19 11:29:18 -06:00
|
|
|
DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2007-06-29 17:37:01 -06:00
|
|
|
bool xgi_dvi_irq_handler(struct xgi_info * info)
|
2007-06-26 14:10:30 -06:00
|
|
|
{
|
2007-06-29 17:37:01 -06:00
|
|
|
bool ret = FALSE;
|
2007-07-19 11:29:18 -06:00
|
|
|
const u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
|
2007-06-26 14:10:30 -06:00
|
|
|
|
2007-07-19 11:29:18 -06:00
|
|
|
if (IN3CFB(info->mmio_map, 0x38) & 0x20) { // DVI interrupt just happened
|
|
|
|
const u8 save_3x4 = DRM_READ8(info->mmio_map, 0x3d4);
|
2007-06-29 17:41:32 -06:00
|
|
|
u8 op3cf_39;
|
|
|
|
u8 op3cf_37;
|
|
|
|
u8 op3x5_5a;
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
// What happened?
|
2007-07-19 11:29:18 -06:00
|
|
|
op3cf_37 = IN3CFB(info->mmio_map, 0x37);
|
2007-06-26 14:46:36 -06:00
|
|
|
|
2007-06-26 14:10:30 -06:00
|
|
|
//Notify BIOS that DVI plug/unplug happened
|
2007-07-19 11:29:18 -06:00
|
|
|
op3x5_5a = IN3X5B(info->mmio_map, 0x5a);
|
|
|
|
OUT3X5B(info->mmio_map, 0x5a, op3x5_5a & 0xf7);
|
2007-06-26 14:10:30 -06:00
|
|
|
|
2007-07-19 11:29:18 -06:00
|
|
|
DRM_WRITE8(info->mmio_map, 0x3d4, save_3x4);
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
// Clear DVI interrupt
|
2007-07-19 11:29:18 -06:00
|
|
|
op3cf_39 = IN3CFB(info->mmio_map, 0x39);
|
|
|
|
OUT3C5B(info->mmio_map, 0x39, (op3cf_39 & ~0x01)); //Set 3cf.39 bit 0 to 0
|
|
|
|
OUT3C5B(info->mmio_map, 0x39, (op3cf_39 | 0x01)); //Set 3cf.39 bit 0 to 1
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
2007-07-19 11:29:18 -06:00
|
|
|
DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2007-07-19 11:29:18 -06:00
|
|
|
|
2007-07-31 18:27:00 -06:00
|
|
|
static void dump_reg_header(unsigned regbase)
|
2007-06-26 14:10:30 -06:00
|
|
|
{
|
2007-07-31 18:27:00 -06:00
|
|
|
printk("\n=====xgi_dump_register========0x%x===============\n",
|
|
|
|
regbase);
|
|
|
|
printk(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
|
|
|
|
}
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
|
2007-07-31 18:27:00 -06:00
|
|
|
static void dump_indexed_reg(struct xgi_info * info, unsigned regbase)
|
|
|
|
{
|
|
|
|
unsigned i, j;
|
|
|
|
u8 temp;
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
|
2007-07-31 18:27:00 -06:00
|
|
|
dump_reg_header(regbase);
|
2007-06-26 14:10:30 -06:00
|
|
|
for (i = 0; i < 0x10; i++) {
|
|
|
|
printk("%1x ", i);
|
|
|
|
|
|
|
|
for (j = 0; j < 0x10; j++) {
|
2007-07-31 18:27:00 -06:00
|
|
|
DRM_WRITE8(info->mmio_map, regbase - 1,
|
|
|
|
(i * 0x10) + j);
|
|
|
|
temp = DRM_READ8(info->mmio_map, regbase);
|
2007-06-26 14:10:30 -06:00
|
|
|
printk("%3x", temp);
|
|
|
|
}
|
2007-07-31 18:27:00 -06:00
|
|
|
printk("\n");
|
2007-06-26 14:10:30 -06:00
|
|
|
}
|
2007-07-31 18:27:00 -06:00
|
|
|
}
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
|
2007-07-31 18:27:00 -06:00
|
|
|
static void dump_reg(struct xgi_info * info, unsigned regbase, unsigned range)
|
|
|
|
{
|
|
|
|
unsigned i, j;
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
|
2007-07-31 18:27:00 -06:00
|
|
|
dump_reg_header(regbase);
|
|
|
|
for (i = 0; i < range; i++) {
|
2007-06-26 14:10:30 -06:00
|
|
|
printk("%1x ", i);
|
|
|
|
|
|
|
|
for (j = 0; j < 0x10; j++) {
|
2007-07-31 18:27:00 -06:00
|
|
|
u8 temp = DRM_READ8(info->mmio_map,
|
|
|
|
regbase + (i * 0x10) + j);
|
2007-06-26 14:10:30 -06:00
|
|
|
printk("%3x", temp);
|
|
|
|
}
|
2007-07-31 18:27:00 -06:00
|
|
|
printk("\n");
|
2007-06-26 14:10:30 -06:00
|
|
|
}
|
2007-07-31 18:27:00 -06:00
|
|
|
}
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
|
2007-07-31 18:27:00 -06:00
|
|
|
void xgi_dump_register(struct xgi_info * info)
|
|
|
|
{
|
|
|
|
dump_indexed_reg(info, 0x3c5);
|
|
|
|
dump_indexed_reg(info, 0x3d5);
|
|
|
|
dump_indexed_reg(info, 0x3cf);
|
|
|
|
|
|
|
|
dump_reg(info, 0xB000, 0x05);
|
|
|
|
dump_reg(info, 0x2200, 0x0B);
|
|
|
|
dump_reg(info, 0x2300, 0x07);
|
|
|
|
dump_reg(info, 0x2400, 0x10);
|
|
|
|
dump_reg(info, 0x2800, 0x10);
|
2007-06-26 14:10:30 -06:00
|
|
|
}
|
|
|
|
|
2007-07-19 11:29:18 -06:00
|
|
|
|
2007-07-27 16:45:59 -06:00
|
|
|
int xgi_dump_register_ioctl(struct drm_device * dev, void * data,
|
|
|
|
struct drm_file * filp)
|
2007-06-26 14:10:30 -06:00
|
|
|
{
|
2007-07-19 11:29:18 -06:00
|
|
|
struct xgi_info *info = dev->dev_private;
|
|
|
|
|
|
|
|
xgi_dump_register(info);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-27 16:45:59 -06:00
|
|
|
int xgi_restore_registers_ioctl(struct drm_device * dev, void * data,
|
|
|
|
struct drm_file * filp)
|
2007-07-19 11:29:18 -06:00
|
|
|
{
|
|
|
|
struct xgi_info *info = dev->dev_private;
|
|
|
|
|
|
|
|
OUT3X5B(info->mmio_map, 0x13, 0);
|
|
|
|
OUT3X5B(info->mmio_map, 0x8b, 2);
|
|
|
|
return 0;
|
2007-06-26 14:10:30 -06:00
|
|
|
}
|
|
|
|
|
2007-07-30 11:02:46 -06:00
|
|
|
|
|
|
|
#define WHOLD_GE_STATUS 0x2800
|
|
|
|
|
|
|
|
/* Test everything except the "whole GE busy" bit, the "master engine busy"
|
|
|
|
* bit, and the reserved bits [26:21].
|
|
|
|
*/
|
|
|
|
#define IDLE_MASK ~((1U<<31) | (1U<<28) | (0x3f<<21))
|
|
|
|
|
2007-06-29 16:27:38 -06:00
|
|
|
void xgi_waitfor_pci_idle(struct xgi_info * info)
|
2007-06-26 14:10:30 -06:00
|
|
|
{
|
2007-07-30 11:02:46 -06:00
|
|
|
unsigned int idleCount = 0;
|
|
|
|
u32 old_status = 0;
|
|
|
|
unsigned int same_count = 0;
|
2007-06-26 14:10:30 -06:00
|
|
|
|
|
|
|
while (idleCount < 5) {
|
2007-07-30 11:02:46 -06:00
|
|
|
const u32 status = DRM_READ32(info->mmio_map, WHOLD_GE_STATUS)
|
|
|
|
& IDLE_MASK;
|
|
|
|
|
|
|
|
if (status == old_status) {
|
|
|
|
same_count++;
|
|
|
|
|
|
|
|
if ((same_count % 100) == 0) {
|
|
|
|
DRM_ERROR("GE status stuck at 0x%08x for %u iterations!\n",
|
|
|
|
old_status, same_count);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
old_status = status;
|
|
|
|
same_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status != 0) {
|
|
|
|
msleep(1);
|
2007-06-26 14:10:30 -06:00
|
|
|
idleCount = 0;
|
|
|
|
} else {
|
|
|
|
idleCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|