📄 mailbox.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 + -