 /* Certain states, on error conditions, can lock up a CPU because they are effectively in an infinite loop with CALL_WITHOUT_DELAY (right back here with time == 0). Prevent infinite lockup by ALWAYS decrementing timeout. */  /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT (noticed in ipmi_smic_sm.c January 2004) */  if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100; 
static enum si_sm_result bt_event(struct si_sm_data *bt, long time){	unsigned char status;	char buf[40]; /* For getting status */	int i;	status = BT_STATUS;	bt->nonzero_status |= status;	if ((bt_debug & BT_DEBUG_STATES) && (bt->state != bt->last_state))		printk(KERN_WARNING "BT: %s %s TO=%ld - %ld \n",			STATE2TXT,			STATUS2TXT(buf),			bt->timeout,			time);	bt->last_state = bt->state;	if (bt->state == BT_STATE_HOSED)	       return SI_SM_HOSED;	if (bt->state != BT_STATE_IDLE) {	/* do timeout test */		/* Certain states, on error conditions, can lock up a CPU		   because they are effectively in an infinite loop with		   CALL_WITHOUT_DELAY (right back here with time == 0).		   Prevent infinite lockup by ALWAYS decrementing timeout. */    	/* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT              (noticed in ipmi_smic_sm.c January 2004) */		if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT))		       time = 100;		bt->timeout -= time;		if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) {			error_recovery(bt, "timed out");			return SI_SM_CALL_WITHOUT_DELAY;		}	}	switch (bt->state) {    	case BT_STATE_IDLE:	/* check for asynchronous messages */		if (status & BT_SMS_ATN) {			BT_CONTROL(BT_SMS_ATN);	/* clear it */			return SI_SM_ATTN;		}		return SI_SM_IDLE;	case BT_STATE_XACTION_START:		if (status & BT_H_BUSY) {			BT_CONTROL(BT_H_BUSY);			break;		}    		if (status & BT_B2H_ATN)		       break;		bt->state = BT_STATE_WRITE_BYTES;		return SI_SM_CALL_WITHOUT_DELAY;	/* for logging */	case BT_STATE_WRITE_BYTES:		if (status & (BT_B_BUSY | BT_H2B_ATN))		       break;		BT_CONTROL(BT_CLR_WR_PTR);		write_all_bytes(bt);		BT_CONTROL(BT_H2B_ATN);	/* clears too fast to catch? */		bt->state = BT_STATE_WRITE_CONSUME;		return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */	case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */        	if (status & (BT_H2B_ATN | BT_B_BUSY))		       break;		bt->state = BT_STATE_B2H_WAIT;		/* fall through with status */	/* Stay in BT_STATE_B2H_WAIT until a packet matches.  However, spinning	   hard here, constantly reading status, seems to hold off the	   generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */	case BT_STATE_B2H_WAIT:    		if (!(status & BT_B2H_ATN))		       break;		/* Assume ordered, uncached writes: no need to wait */		if (!(status & BT_H_BUSY))		       BT_CONTROL(BT_H_BUSY); /* set */		BT_CONTROL(BT_B2H_ATN);		/* clear it, ACK to the BMC */		BT_CONTROL(BT_CLR_RD_PTR);	/* reset the queue */		i = read_all_bytes(bt);		BT_CONTROL(BT_H_BUSY);		/* clear */		if (!i)				/* Try this state again */		       break;		bt->state = BT_STATE_READ_END;		return SI_SM_CALL_WITHOUT_DELAY;	/* for logging */    	case BT_STATE_READ_END:		/* I could wait on BT_H_BUSY to go clear for a truly clean		   exit.  However, this is already done in XACTION_START		   and the (possible) extra loop/status/possible wait affects		   performance.  So, as long as it works, just ignore H_BUSY */#ifdef MAKE_THIS_TRUE_IF_NECESSARY		if (status & BT_H_BUSY)		       break;#endif		bt->seq++;		bt->state = BT_STATE_IDLE;		return SI_SM_TRANSACTION_COMPLETE;	case BT_STATE_RESET1:    		reset_flags(bt);    		bt->timeout = BT_RESET_DELAY;		bt->state = BT_STATE_RESET2;		break;	case BT_STATE_RESET2:		/* Send a soft reset */		BT_CONTROL(BT_CLR_WR_PTR);		HOST2BMC(3);		/* number of bytes following */		HOST2BMC(0x18);		/* NetFn/LUN == Application, LUN 0 */		HOST2BMC(42);		/* Sequence number */		HOST2BMC(3);		/* Cmd == Soft reset */		BT_CONTROL(BT_H2B_ATN);		bt->state = BT_STATE_RESET3;		break;	case BT_STATE_RESET3:		if (bt->timeout > 0)		       return SI_SM_CALL_WITH_DELAY;		bt->state = BT_STATE_RESTART;	/* printk in debug modes */		break;	case BT_STATE_RESTART:		/* don't reset retries! */		bt->write_data[2] = ++bt->seq;		bt->read_count = 0;		bt->nonzero_status = 0;		bt->timeout = BT_NORMAL_TIMEOUT;		bt->state = BT_STATE_XACTION_START;		break;	default:	/* HOSED is supposed to be caught much earlier */		error_recovery(bt, "internal logic error");		break;  	}  	return SI_SM_CALL_WITH_DELAY;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/c4edff1c19ef23e15aae64ca03f32c6719822d54/ipmi_bt_sm.c/clean/drivers/char/ipmi/ipmi_bt_sm.c