Esempio n. 1
0
// send a command to the keyboard.  re-sends if requested.
// returns 0 if the keyboard response is bad, otherwise
// returns the response data.
unsigned char send_kbd_cmd(unsigned char data)
{
	unsigned char temp;
	int i;

	// flush obf
	flush_obf();

	// send the first time
	check_ibf();
	pucPtr[HT6542_DAT] = data;
	u_sleep(10);

	for (i = 0; i < HT6542_MAX_RESENDS; i++)
	{
		if(!check_tx())
		{
			check_obf();
			temp = pucPtr[HT6542_DAT];

			if (temp == 0x30)
			{
				check_obf();
				temp = pucPtr[HT6542_DAT];
			}

			if( temp == KBD_STAT_RESEND)
			{
				pucPtr[HT6542_DAT] = data;
			}
			else	// if not re-send, then see if it's ack
			{
				if(temp == KBD_STAT_ACK)
				{
					return temp;
				}
				else 	// not re-send or ack so return with error
				{
					xxcprintf(g_e, "No Resend or ACK, data %x\n", temp);
					return temp;
				}
			}
		} // if !check_tx
		else
		{
			xxcprintf(g_e, "TX Timeout\n");
			return 1;		
		}
	} // while 1

	xxcprintf(g_e, "Too many resends\n");
	return 1;		
} // main
Esempio n. 2
0
/*
 * This implements the state machine defined in the IPMI manual, see
 * that for details on how this works.  Divide that flowchart into
 * sections delimited by "Wait for IBF" and this will become clear.
 */
static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
{
	unsigned char status;
	unsigned char state;

	status = read_status(kcs);

	if (kcs_debug & KCS_DEBUG_STATES)
		printk(KERN_DEBUG "KCS: State = %d, %x\n", kcs->state, status);

	/* All states wait for ibf, so just do it here. */
	if (!check_ibf(kcs, status, time))
		return SI_SM_CALL_WITH_DELAY;

	/* Just about everything looks at the KCS state, so grab that, too. */
	state = GET_STATUS_STATE(status);

	switch (kcs->state) {
	case KCS_IDLE:
		/* If there's and interrupt source, turn it off. */
		clear_obf(kcs, status);

		if (GET_STATUS_ATN(status))
			return SI_SM_ATTN;
		else
			return SI_SM_IDLE;

	case KCS_START_OP:
		if (state != KCS_IDLE_STATE) {
			start_error_recovery(kcs,
					     "State machine not idle at start");
			break;
		}

		clear_obf(kcs, status);
		write_cmd(kcs, KCS_WRITE_START);
		kcs->state = KCS_WAIT_WRITE_START;
		break;

	case KCS_WAIT_WRITE_START:
		if (state != KCS_WRITE_STATE) {
			start_error_recovery(
				kcs,
				"Not in write state at write start");
			break;
		}
		read_data(kcs);
		if (kcs->write_count == 1) {
			write_cmd(kcs, KCS_WRITE_END);
			kcs->state = KCS_WAIT_WRITE_END;
		} else {
			write_next_byte(kcs);
			kcs->state = KCS_WAIT_WRITE;
		}
		break;

	case KCS_WAIT_WRITE:
		if (state != KCS_WRITE_STATE) {
			start_error_recovery(kcs,
					     "Not in write state for write");
			break;
		}
		clear_obf(kcs, status);
		if (kcs->write_count == 1) {
			write_cmd(kcs, KCS_WRITE_END);
			kcs->state = KCS_WAIT_WRITE_END;
		} else {
			write_next_byte(kcs);
		}
		break;

	case KCS_WAIT_WRITE_END:
		if (state != KCS_WRITE_STATE) {
			start_error_recovery(kcs,
					     "Not in write state"
					     " for write end");
			break;
		}
		clear_obf(kcs, status);
		write_next_byte(kcs);
		kcs->state = KCS_WAIT_READ;
		break;

	case KCS_WAIT_READ:
		if ((state != KCS_READ_STATE) && (state != KCS_IDLE_STATE)) {
			start_error_recovery(
				kcs,
				"Not in read or idle in read state");
			break;
		}

		if (state == KCS_READ_STATE) {
			if (!check_obf(kcs, status, time))
				return SI_SM_CALL_WITH_DELAY;
			read_next_byte(kcs);
		} else {
			/*
			 * We don't implement this exactly like the state
			 * machine in the spec.  Some broken hardware
			 * does not write the final dummy byte to the
			 * read register.  Thus obf will never go high
			 * here.  We just go straight to idle, and we
			 * handle clearing out obf in idle state if it
			 * happens to come in.
			 */
			clear_obf(kcs, status);
			kcs->orig_write_count = 0;
			kcs->state = KCS_IDLE;
			return SI_SM_TRANSACTION_COMPLETE;
		}
		break;

	case KCS_ERROR0:
		clear_obf(kcs, status);
		status = read_status(kcs);
		if (GET_STATUS_OBF(status))
			/* controller isn't responding */
			if (time_before(jiffies, kcs->error0_timeout))
				return SI_SM_CALL_WITH_TICK_DELAY;
		write_cmd(kcs, KCS_GET_STATUS_ABORT);
		kcs->state = KCS_ERROR1;
		break;

	case KCS_ERROR1:
		clear_obf(kcs, status);
		write_data(kcs, 0);
		kcs->state = KCS_ERROR2;
		break;

	case KCS_ERROR2:
		if (state != KCS_READ_STATE) {
			start_error_recovery(kcs,
					     "Not in read state for error2");
			break;
		}
		if (!check_obf(kcs, status, time))
			return SI_SM_CALL_WITH_DELAY;

		clear_obf(kcs, status);
		write_data(kcs, KCS_READ_BYTE);
		kcs->state = KCS_ERROR3;
		break;

	case KCS_ERROR3:
		if (state != KCS_IDLE_STATE) {
			start_error_recovery(kcs,
					     "Not in idle state for error3");
			break;
		}

		if (!check_obf(kcs, status, time))
			return SI_SM_CALL_WITH_DELAY;

		clear_obf(kcs, status);
		if (kcs->orig_write_count) {
			restart_kcs_transaction(kcs);
		} else {
			kcs->state = KCS_IDLE;
			return SI_SM_TRANSACTION_COMPLETE;
		}
		break;

	case KCS_HOSED:
		break;
	}

	if (kcs->state == KCS_HOSED) {
		init_kcs_data(kcs, kcs->io);
		return SI_SM_HOSED;
	}

	return SI_SM_CALL_WITHOUT_DELAY;
}
Esempio n. 3
0
int test_keyboard()
{
	unsigned char data;
	volatile unsigned char test, test1;
	unsigned long testl;

	// set up CS4 for 8-bits, 4 wait states
	// start by clearing the CS4 field
	pulPtr[HwMemConfig2 >> 2] &= 0xffffff00;

	// now get the boot width and set CS4 accordingly
	testl = (pulPtr[HwStatus >> 2] >> 27) & 0x3;		// boot width is in bits 27 and 28 of HwStatus
	switch(testl)
	{
		case 0:	// we booted in 32-bit mode
			pulPtr[HwMemConfig2 >> 2] |= (0x00000090 | 2); 
			break;

		case 1:	// we booted in 8-bit mode
			pulPtr[HwMemConfig2 >> 2] |= (0x00000090 | 0); 
			break;

		case 2:	// we booted in 16-bit mode
			pulPtr[HwMemConfig2 >> 2] |= (0x00000090 | 3); 
			break;
	}

	// flush any pending data
	flush_obf();

	// see if we can run the controller self test
	xxcprintf(g_e, "Starting 6542 Internal Diagnostic Test\n");
	pucPtr[HT6542_CMD] = HT6542_CMD_DIAG;

	// check the status for completion
	// wait until the ibf flag goes false
	check_ibf();

	// now see if we have output data
	check_obf();
	data = pucPtr[HT6542_DAT];
	if(data == KBD_STAT_DIAG_OK)
	{
		xxcprintf(g_e, "HT6542B Internal Diagnostic Test Passed\n");
		xxcprintf(g_e, "Data Port = 0x%02x\n",data);
	}
	else
	{
		xxcprintf(g_e, "HT6542B Internal Diagnostic Test Failed\n");
		xxcprintf(g_e, "Data Port = 0x%02x\n",data);
		return -1;
	}

	// next we test the keyboard and mouse ports
	xxcprintf(g_e, "Starting HT6542B Keyboard Port Test\n");
	check_ibf();
	pucPtr[HT6542_CMD] = HT6542_CMD_KBD_TEST;
		
	// check the status for completion
	// wait until the ibf flag goes false
	check_ibf();

	// now see if we have output data
	check_obf();

	data = pucPtr[HT6542_DAT];
	if(data == 0)	// anything but zero is a failure
	{
		xxcprintf(g_e, "HT6542B Keyboard Port Test Passed\n");
		xxcprintf(g_e, "Data Port = 0x%02x\n",data);
	}
	else
	{
		xxcprintf(g_e, "HT6542B Keyboard Port Test Failed\n");
		xxcprintf(g_e, "Data Port = 0x%02x\n",data);
	}

	xxcprintf(g_e, "Starting HT6542B Mouse Port Test\n");
	check_ibf();
	pucPtr[HT6542_CMD] = HT6542_CMD_AUX_TEST;
		
	// check the status for completion
	// wait until the ibf flag goes false
	check_ibf();

	// now see if we have output data
	check_obf();
	data = pucPtr[HT6542_DAT];
	if(data == 0)	// anything but zero is a failure
	{
		xxcprintf(g_e, "HT6542B Mouse Port Test Passed\n");
		xxcprintf(g_e, "Data Port = 0x%02x\n",data);
	}
	else
	{
		xxcprintf(g_e, "HT6542B Mouse Port Test Failed\n");
		xxcprintf(g_e, "Data Port = 0x%02x\n",data);
	}

	// next enable interrupts
	xxcprintf(g_e, "Enable Interrupts\n");
	check_ibf();
	pucPtr[HT6542_CMD] = HT6542_CMD_SET_BYTE;
	check_ibf();

	// send the interrupt enable byte
	pucPtr[HT6542_CMD] = (HT6542_CMD_BYTE_AUX_INT | HT6542_CMD_BYTE_KBD_INT);
	check_ibf();

	// get it back to check it
	pucPtr[HT6542_CMD] = HT6542_CMD_GET_BYTE;
	check_ibf();

	// now see if we have output data
	check_obf();
	data = pucPtr[HT6542_DAT];
	xxcprintf(g_e, "Enable Interrupts Status = %02x\n", data);


	// next we see if we have a keyboard attached.  if we don't
	// we will get a tx timeout status.  if we do, we will get
	// an 0xFA followed by 0xAA.

	xxcprintf(g_e, "Detecting Keyboard Presence\n");
	test = send_kbd_cmd(KBD_CMD_RST);

	if(test != KBD_STAT_ACK)
	{
		xxcprintf(g_e, "No ACK from Keyboard, Received 0x%02x\n", test);
		return 0;
	}

	check_obf();
	test = pucPtr[HT6542_DAT];
	xxcprintf(g_e, "Got %x\n", test);

	if (test != KBD_STAT_RST_OK)
	{
		xxcprintf(g_e, "Keyboard Reset Failed\n");
		return 0;
	}

	xxcprintf(g_e, "Keyboard Detected\n");

	// get the ID of the keyboard

	xxcprintf(g_e, "Detecting Keyboard ID\n");
	test = send_kbd_cmd(KBD_CMD_ID);
	if(test != KBD_STAT_ACK)
	{
		xxcprintf(g_e, "No ACK from Keyboard, Received 0x%02x\n", test);
		return 0;

	}

	check_obf();
	test = pucPtr[HT6542_DAT];
	if(test == KBD_CMD_ID_1ST)	// 1st byte of ID?
	{
		xxcprintf(g_e, "Received Valid ID\n");

		check_obf();
		test1 = pucPtr[HT6542_DAT];
		xxcprintf(g_e, "Keyboard ID = 0x%02x%02x\n",test,test1);
	}
	else
	{
		xxcprintf(g_e, "Bad ID Received, 0x%02x\n", test);
	}

	return 1;
} // main
static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
{
	unsigned char status;
	unsigned char state;

	status = read_status(kcs);

	if (kcs_debug & KCS_DEBUG_STATES)
		printk(KERN_DEBUG "KCS: State = %d, %x\n", kcs->state, status);

	
	if (!check_ibf(kcs, status, time))
		return SI_SM_CALL_WITH_DELAY;

	
	state = GET_STATUS_STATE(status);

	switch (kcs->state) {
	case KCS_IDLE:
		
		clear_obf(kcs, status);

		if (GET_STATUS_ATN(status))
			return SI_SM_ATTN;
		else
			return SI_SM_IDLE;

	case KCS_START_OP:
		if (state != KCS_IDLE_STATE) {
			start_error_recovery(kcs,
					     "State machine not idle at start");
			break;
		}

		clear_obf(kcs, status);
		write_cmd(kcs, KCS_WRITE_START);
		kcs->state = KCS_WAIT_WRITE_START;
		break;

	case KCS_WAIT_WRITE_START:
		if (state != KCS_WRITE_STATE) {
			start_error_recovery(
				kcs,
				"Not in write state at write start");
			break;
		}
		read_data(kcs);
		if (kcs->write_count == 1) {
			write_cmd(kcs, KCS_WRITE_END);
			kcs->state = KCS_WAIT_WRITE_END;
		} else {
			write_next_byte(kcs);
			kcs->state = KCS_WAIT_WRITE;
		}
		break;

	case KCS_WAIT_WRITE:
		if (state != KCS_WRITE_STATE) {
			start_error_recovery(kcs,
					     "Not in write state for write");
			break;
		}
		clear_obf(kcs, status);
		if (kcs->write_count == 1) {
			write_cmd(kcs, KCS_WRITE_END);
			kcs->state = KCS_WAIT_WRITE_END;
		} else {
			write_next_byte(kcs);
		}
		break;

	case KCS_WAIT_WRITE_END:
		if (state != KCS_WRITE_STATE) {
			start_error_recovery(kcs,
					     "Not in write state"
					     " for write end");
			break;
		}
		clear_obf(kcs, status);
		write_next_byte(kcs);
		kcs->state = KCS_WAIT_READ;
		break;

	case KCS_WAIT_READ:
		if ((state != KCS_READ_STATE) && (state != KCS_IDLE_STATE)) {
			start_error_recovery(
				kcs,
				"Not in read or idle in read state");
			break;
		}

		if (state == KCS_READ_STATE) {
			if (!check_obf(kcs, status, time))
				return SI_SM_CALL_WITH_DELAY;
			read_next_byte(kcs);
		} else {
			clear_obf(kcs, status);
			kcs->orig_write_count = 0;
			kcs->state = KCS_IDLE;
			return SI_SM_TRANSACTION_COMPLETE;
		}
		break;

	case KCS_ERROR0:
		clear_obf(kcs, status);
		status = read_status(kcs);
		if (GET_STATUS_OBF(status))
			
			if (time_before(jiffies, kcs->error0_timeout))
				return SI_SM_CALL_WITH_TICK_DELAY;
		write_cmd(kcs, KCS_GET_STATUS_ABORT);
		kcs->state = KCS_ERROR1;
		break;

	case KCS_ERROR1:
		clear_obf(kcs, status);
		write_data(kcs, 0);
		kcs->state = KCS_ERROR2;
		break;

	case KCS_ERROR2:
		if (state != KCS_READ_STATE) {
			start_error_recovery(kcs,
					     "Not in read state for error2");
			break;
		}
		if (!check_obf(kcs, status, time))
			return SI_SM_CALL_WITH_DELAY;

		clear_obf(kcs, status);
		write_data(kcs, KCS_READ_BYTE);
		kcs->state = KCS_ERROR3;
		break;

	case KCS_ERROR3:
		if (state != KCS_IDLE_STATE) {
			start_error_recovery(kcs,
					     "Not in idle state for error3");
			break;
		}

		if (!check_obf(kcs, status, time))
			return SI_SM_CALL_WITH_DELAY;

		clear_obf(kcs, status);
		if (kcs->orig_write_count) {
			restart_kcs_transaction(kcs);
		} else {
			kcs->state = KCS_IDLE;
			return SI_SM_TRANSACTION_COMPLETE;
		}
		break;

	case KCS_HOSED:
		break;
	}

	if (kcs->state == KCS_HOSED) {
		init_kcs_data(kcs, kcs->io);
		return SI_SM_HOSED;
	}

	return SI_SM_CALL_WITHOUT_DELAY;
}