⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mailbox.c

📁 详细介绍了一篇关于pci开发的接口芯片
💻 C
字号:
/* mailbox.c

	Common mailbox routines.
	Tests are in other files.

	*******  Mailbox Interrupt Notes  *********

 The interupt enable bit masks a signal that goes to a flop. 
 The output of the flop is the interrupt, and it can only be 
 cleared by writing a '1'  (even if you "disable" the interupt).
 The interrupt status bit you read is also the output of the flop.

*/

#include <stdtypes.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* non-standard includes... */
#include <lib.h>
#include <main.h>
#include <mailbox.h>

/* **************************************************** */
/*					Defines         					*/
/* **************************************************** */

extern struct _chip chip_uut, chip_control;
extern CHAR errstring[];
extern CHAR text[];

#define CHECK_OFFSET if( (offset>3) || (offset<0) ) { fprintf( stderr, "OFFSET Programming error in mailbox I/O.\n" ); exit(1); }

/* **************************************************** */
/*				Common functions						*/
/* **************************************************** */

UINT8 mailbox_read8( UINT16 flag, int offset )
/*	
	Read incoming mailbox.

	Entry:	flag - must be MB_PCI or MB_ADDON 
			offset - which byte offset 0-3
*/
{
	CHECK_OFFSET
	if ( flag & MB_PCI )
		return( region_read8( &chip_uut, 0, IMB + offset ) );
	else
		return( addon_read8( AIMB + offset ) );
}

UINT16 mailbox_read16( UINT16 flag, int offset )
/*	
	Read incoming mailbox.

	Entry:	flag - must be MB_PCI or MB_ADDON 
			offset - which byte offset 0 or 2
*/
{
	CHECK_OFFSET
	if ( flag & MB_PCI )
		return( region_read16( &chip_uut, 0, IMB + offset ) );
	else
		return( addon_read16( AIMB + offset ) );
}


UINT32 mailbox_read32( UINT16 flag )
/*	
	Read incoming mailbox.

	Entry:	flag - must be MB_PCI or MB_ADDON 
			no offset required for 32-bit
*/
{
	if ( flag & MB_PCI )
		return( region_read32( &chip_uut, 0, IMB ) );
	else
		return( addon_read32( AIMB ) );
}

VOID mailbox_write8( UINT16 flag, int offset, UINT8 data )
/*	
	Write outgoing mailbox.

	Entry:	flag - must be MB_PCI or MB_ADDON 
			offset - which byte offset 0-3
			data - 3 guesses
*/
{
	CHECK_OFFSET
	if ( flag & MB_PCI )
		region_write8( &chip_uut, 0, OMB + offset, data );
	else
		addon_write8( AOMB + offset, data );
}

VOID mailbox_write16( UINT16 flag, int offset, UINT16 data )
/*	
	Write outgoing mailbox.

	Entry:	flag - must be MB_PCI or MB_ADDON 
			offset - which byte offset 0-3
			data - 3 guesses
*/
{
	CHECK_OFFSET
	if ( flag & MB_PCI )
		region_write16( &chip_uut, 0, OMB + offset, data );
	else
		addon_write16( AOMB + offset, data );
}

VOID mailbox_write32( UINT16 flag, UINT32 data )
/*	
	Write outgoing mailbox.

	Entry:	flag - must be MB_PCI or MB_ADDON 
			no offset for 32-bit
			data - 3 guesses
*/
{
	if ( flag & MB_PCI )
		region_write32( &chip_uut, 0, OMB, data );
	else
		addon_write32( AOMB, data );
}


int mailbox_int_active( UINT16 flag )
/*
	Test if there is an interrupt caused by an inbound or
	outbound mailbox. The interrupt is tested by looking at the
	pcb signal, then the source is check to see if the
	requested mailbox int is active.

	Entry:	flag - must be MB_PCI and/or MB_ADDON
	Return:	TRUE if interrupt pin is asserted due to a mailbox interrupt.
*/
{
	if (mailbox_outbound_int_active(flag) | mailbox_inbound_int_active(flag) )
		return( TRUE );

 	return( FALSE );
}

int mailbox_outbound_int_active( UINT16 flag )
/* 	
	Entry:	flag - must be MB_PCI and/or MB_ADDON
	Return:	TRUE if interrupt pin is asserted due to a outbound 
			mailbox interrupt.

*/
{
	UINT32 status;

	if ( (flag & MB_PCI) && pci_int_active()  )
	{
		status = region_read32( &chip_uut, 0, INTCSR );
		if ( status & INTCSR_OMB_INT )  return TRUE;
	}

	if ( (flag & MB_ADDON) && addon_int_active() )
	{
		status = addon_read32( AINT );
		if ( status & AINT_OMB_INT ) return TRUE;
	}

	return FALSE;
}

int mailbox_inbound_int_active( UINT16 flag )
/*
	Entry:	flag - must be MB_PCI and/or MB_ADDON
	Return:	TRUE if interrupt pin is asserted due to a inbound 
			mailbox interrupt.

*/
{
	UINT32 status;

	if ( (flag & MB_PCI) && pci_int_active()  )
	{
		status = region_read32( &chip_uut, 0, INTCSR );
		if ( status & INTCSR_IMB_INT )  return TRUE;
	}

	if ( (flag & MB_ADDON) && addon_int_active() )
	{
		status = addon_read32( AINT );
		if ( status & AINT_IMB_INT ) return TRUE;
	}


	return FALSE;
}


VOID mailbox_reset_flags( UINT16 flag )
/*
	Resets mailbox flags (only one control bit) from PCI and/or Addon side.

	Entry:	flag - must be MB_PCI and/or MB_ADDON
			set bit position (e.g. if bit 0 set, reset lane 0).
	Return:	N/A

*/
{
	UINT32 data32;

	/* read interrupt/control status reg... */
	if ( flag & MB_PCI )
	{
		data32 = region_read32( &chip_uut, 0, RCR );
		data32 |= 0x08000000L;
		region_write32( &chip_uut, 0, RCR, data32 );
	}

	if ( flag & MB_ADDON )
	{
		data32 = addon_read32( ARCR );
		data32 |= 0x08000000L;
		addon_write32( ARCR, data32 );
	}

}

int read_omb_status( UINT16 flag )
/*
	Reads mailbox flags and returns the four outbound 
	status bits for the requested owner in the low nibble.

	Entry:	flag - must be MB_PCI or MB_ADDON
			set bit position (e.g. if bit 0 set, reset lane 0).
	Return:	the four status bits as int

*/
{
	UINT32 data32 = 0;

	if ( flag & MB_PCI )
	{
		data32 = region_read32( &chip_uut, 0, MBEF );
		data32 = data32 >> 12;
	}

	else if ( flag & MB_ADDON )
	{
		data32 = addon_read32( AMBEF );
		data32 = data32 >> 28;
	}

	data32 &= 0xFL;
	return( (int)data32 );

}

int read_inb_status( UINT16 flag )
/*
	Reads mailbox flags and returns the four inbound 
	status bits for the requested owner in the low nibble.

	Entry:	flag - must be MB_PCI or MB_ADDON
			set bit position (e.g. if bit 0 set, reset lane 0).
	Return:	the four status bits as int

*/
{
	UINT32 data32 = 0;

	if ( flag & MB_PCI )
	{
		data32 = region_read32( &chip_uut, 0, MBEF );
		data32 = data32 >> 28;
	}

	else if ( flag & MB_ADDON )
	{
		data32 = addon_read32( AMBEF );
		data32 = data32 >> 12;
	}

	data32 &= 0xFL;
	return( (int)data32 );

}

/* read/write PCI or addon RCR based on "owner"... */
UINT32 mailbox_read_rcr32( UINT16 owner )
{
	if ( owner & MB_PCI )
		return ( region_read32( &chip_uut, 0, RCR ) );
	else
		return ( addon_read32( ARCR ) );
}

VOID mailbox_write_rcr32( UINT16 owner, UINT32 data32 )
{
	if ( owner & MB_PCI )
		region_write32( &chip_uut, 0, RCR, data32 );
	else
		addon_write32( ARCR, data32 );
}


int check_mbef_status_clear( VOID )
/*
	Check that all mailbox status bits are clear for both sides.
	If either PCI or addon flags are set, this displays them.
*/
{
	int data;

	data = read_omb_status( MB_PCI );
	if ( data != 0 )
	{
		str_owner( MB_PCI );		/* adds "PCI" or "Addon" to errstring */
		sprintf( text, "outbound mailbox status bits SB: 0  WS:%1x.\n", data );
		strcat( errstring, text );
	}

	data = read_inb_status( MB_PCI );
	if ( data != 0 )
	{
		str_owner( MB_PCI );		/* adds "PCI" or "Addon" to errstring */
		sprintf( text, "inbound mailbox status bits SB: 0  WS:%1x.\n", data );
		strcat( errstring, text );
	}

	data = read_omb_status( MB_ADDON );
	if ( data != 0 )
	{
		str_owner( MB_ADDON );		/* adds "PCI" or "Addon" to errstring */
		sprintf( text, "outbound mailbox status bits SB: 0  WS:%1x.\n", data );
		strcat( errstring, text );
	}

	data = read_inb_status( MB_ADDON );
	if ( data != 0 )
	{
		str_owner( MB_ADDON );		/* adds "PCI" or "Addon" to errstring */
		sprintf( text, "inbound mailbox status bits SB: 0  WS:%1x.\n", data );
		strcat( errstring, text );
	}

	return TRUE;
}


VOID str_owner( UINT16 owner )
/* adds "PCI" or "Addon" to errstring */
{
	if( owner & MB_PCI )
		strcat( errstring, "PCI " );
	if( owner & MB_ADDON )
		strcat( errstring, "Addon " );
}

VOID mailbox_enable_int( UINT16 flag, int bytelane )
/*
	Enable an inbound and/or outbound mailbox interrupt for
	PCI and/or addon. Also can select which byte lane causes the
	interrupt.

	Entry:	flag - MB_PCI, MB_ADDON, MB_IN, MB_OUT
			bytelane - which byte to enable
*/
{
	if( flag & MB_PCI )
	{
		if ( flag & MB_IN )
		{
			// disable interrupt and set byte lane to 0...
			bclr_intcsr( INTCSR_IMB_INT_ENABLE | (0x3L << INTCSR_BYTE_ILANE_LOWBIT) );
			// select which byte lane enables int...
			bset_intcsr( (UINT32)bytelane << INTCSR_BYTE_ILANE_LOWBIT );
			// enable interrupt...
			bset_intcsr( INTCSR_IMB_INT_ENABLE );
		}

		if ( flag & MB_OUT )
		{
			bclr_intcsr( INTCSR_OMB_INT_ENABLE | (0x3L << INTCSR_BYTE_OLANE_LOWBIT) );
			bset_intcsr( (UINT32)bytelane << INTCSR_BYTE_OLANE_LOWBIT );
			bset_intcsr( INTCSR_OMB_INT_ENABLE );
		}
	}

	if( flag & MB_ADDON )
	{
		if ( flag & MB_IN )
		{
			bclr_aint( AINT_IMB_INT_ENABLE | (0x3L << AINT_BYTE_ILANE_LOWBIT) );
			bset_aint( (UINT32)bytelane << AINT_BYTE_ILANE_LOWBIT );
			bset_aint( AINT_IMB_INT_ENABLE );
		}

		if ( flag & MB_OUT )
		{
			bclr_aint( AINT_OMB_INT_ENABLE | (0x3L << AINT_BYTE_OLANE_LOWBIT) );
			bset_aint( (UINT32)bytelane << AINT_BYTE_OLANE_LOWBIT );
			bset_aint( AINT_OMB_INT_ENABLE );
		}

	}
}

VOID mailbox_disable_int( UINT16 flag )
/*
	Disable an inbound and/or outbound mailbox interrupt for
	PCI and/or addon.

	Entry:	flag - MB_PCI, MB_ADDON, MB_IN, MB_OUT
*/
{
	if ( (flag & (MB_IN | MB_OUT)) == 0 )
	{
		fprintf( stderr, "Programming error - called mailbox_disable_int\n"
						"without IN or OUT set.\n" );
		exit(1);
	}

	if ( (flag & (MB_PCI | MB_ADDON)) == 0 )
	{
		fprintf( stderr, "Programming error - called mailbox_disable_int\n"
						"without PCI or ADDON set.\n" );
		exit(1);
	}

	if( flag & MB_PCI )
	{
		if ( flag & MB_IN )
			bclr_intcsr( INTCSR_IMB_INT_ENABLE );
		if ( flag & MB_OUT )
			bclr_intcsr( INTCSR_OMB_INT_ENABLE );
	}

	if( flag & MB_ADDON )
	{
		if ( flag & MB_IN )
			bclr_aint( AINT_IMB_INT_ENABLE );
		if ( flag & MB_OUT )
			bclr_aint( AINT_OMB_INT_ENABLE );
	}
}


UINT32 mailbox_read_intcsr32( UINT16 owner )
{
	if ( owner & MB_PCI )
		return ( region_read32( &chip_uut, 0, INTCSR ) );
	else
		return ( addon_read32( AINT ) );
}


VOID mailbox_write_intcsr32( UINT16 owner, UINT32 data32 )
{
	if ( owner & MB_PCI )
		region_write32( &chip_uut, 0, INTCSR, data32 );
	else
		addon_write32( AINT, data32 );
}

VOID bclr_intcsr( UINT32 data )
/*
	Do BCLR for INTCSR. This is done because we always need to write
	0's to certain status bits that can reset interrupt status.
*/
{
	UINT32 data32 = mailbox_read_intcsr32( MB_PCI );

	// drop the status bits that reset their condition...
	data32 &= ~(INTCSR_IMB_INT | INTCSR_OMB_INT);
	data32 &= ~data;	// drop requested bits
	mailbox_write_intcsr32( MB_PCI, data32 );
}


VOID bset_intcsr( UINT32 data )
/*
	Do BSET for INTCSR. This is done because we always need to write
	0's to certain status bits that can reset interrupt status.
*/
{
	UINT32 data32 = mailbox_read_intcsr32( MB_PCI );

	// drop the status bits that reset their condition...
	data32 &= ~(INTCSR_IMB_INT | INTCSR_OMB_INT);
	data32 |= data;			// add requested bits
	mailbox_write_intcsr32( MB_PCI, data32 );
}


VOID bclr_aint( UINT32 data )
/*
	Do BCLR for AINT. This is done because we always need to write
	0's to certain status bits that can reset interrupt status.
*/
{
	UINT32 data32 = addon_read32( AINT );

	// drop the status bits that reset their condition...
	data32 &= ~(AINT_IMB_INT | AINT_OMB_INT);
	data32 &= ~data;	// drop requested bits
	addon_write32( AINT, data32 );
}


VOID bset_aint( UINT32 data )
/*
	Do BSET for AINT. This is done because we always need to write
	0's to certain status bits that can reset interrupt status.
*/
{
	UINT32 data32 = addon_read32( AINT );

	// drop the status bits that reset their condition...
	data32 &= ~(AINT_IMB_INT | AINT_OMB_INT);
	data32 |= data;			// add requested bits
	addon_write32( AINT, data32 );
}


VOID mailbox_clear_int( UINT16 flag )
/*
	Clears inbound and outbound interrupts.

	Entry:	MB_PCI and/or MB_ADDON

*/
{
	mailbox_clear_outbound_int( flag );
	mailbox_clear_inbound_int( flag );
}

VOID mailbox_clear_outbound_int( UINT16 flag )
/*
	Clears outbound interrupts.

	Entry:	MB_PCI and/or MB_ADDON
*/
{
	if ( flag & MB_PCI )
		bset_intcsr( INTCSR_OMB_INT );
	if ( flag & MB_ADDON )
		bset_aint( AINT_OMB_INT );
}

VOID mailbox_clear_inbound_int( UINT16 flag )
/*
	Clears inbound interrupts.

	Entry:	MB_PCI and/or MB_ADDON
*/
{
	if ( flag & MB_PCI )
		bset_intcsr( INTCSR_IMB_INT );
	if ( flag & MB_ADDON )
		bset_aint( AINT_IMB_INT );
}

VOID mailbox_clear_all( VOID )
{
	bset_control_reg( CTRL_LDENB );	// LDENB high so no load
	mailbox_disable_int( MB_PCI | MB_ADDON | MB_IN | MB_OUT );
	mailbox_reset_flags( MB_PCI );
	mailbox_clear_int( MB_PCI | MB_ADDON   );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -