ARPDAS_QNX6 1.0
|
00001 /* hint.c provides all the interrupt functionality (except the 00002 handler itself. 00003 */ 00004 #include <stdlib.h> 00005 #include <errno.h> 00006 #include <sys/neutrino.h> 00007 #include <hw/inout.h> 00008 #include "nortlib.h" 00009 #include "subbus.h" 00010 #include "sc104.h" 00011 00012 static int expint_iid = -1; 00013 int expint_irq = 9; 00014 00015 #define MAX_IRQ_104 12 00016 static unsigned short irq104[ MAX_IRQ_104 ] = { 00017 0, 0, 0, 0x21, 0x22, 0x23, 0x24, 0x25, 0, 0x20, 0x26, 0x27 00018 }; 00019 00020 static int read_one_irq( char **s ) { 00021 int ans; 00022 char *t; 00023 00024 t = *s; 00025 if ( t == 0 || *t == '\0' ) return 0; 00026 ans = strtoul( t, s, 10 ); 00027 if ( t == *s ) ans = 0; 00028 if ( **s == ':' ) (*s)++; 00029 return ans; 00030 } 00031 00032 void process_IRQs( char *t ) { 00033 expint_irq = read_one_irq( &t ); 00034 //spare_irq = read_one_irq( &t ); 00035 //pfail_irq = read_one_irq( &t ); 00036 } 00037 00038 static int int_init( int irq, unsigned short enable, int bit, 00039 int coid, short code, int value ) { 00040 unsigned short cfg_word, cfg_val, cfg_mask; 00041 int iid; 00042 struct sigevent intr_event; 00043 00044 if ( irq < 0 || irq >= MAX_IRQ_104 || irq104[ irq ] == 0 ) 00045 nl_error( 3, "IRQ %d is invalid", irq ); 00046 intr_event.sigev_notify = SIGEV_PULSE; 00047 intr_event.sigev_coid = coid; 00048 intr_event.sigev_priority = SIGEV_PULSE_PRIO_INHERIT; 00049 intr_event.sigev_code = code; 00050 intr_event.sigev_value.sival_int = value; 00051 iid = InterruptAttachEvent(expint_irq, &intr_event, 00052 _NTO_INTR_FLAGS_PROCESS | _NTO_INTR_FLAGS_TRK_MSK ); 00053 if (iid == -1) 00054 nl_error( 3, "Unable to attach IRQ %d: errno %d", irq, errno); 00055 else 00056 nl_error( -2, "Interrupt %d attached: coid=%d code=%d val=%d", 00057 irq, coid, code, value ); 00058 InterruptUnmask( irq, iid ); 00059 if ( subbus_subfunction == SB_SYSCON104 ) { 00060 /* It is theoretically possible to run these cards on a 00061 cable off of an older syscon, so I won't die hard if 00062 this isn't syscon104. 00063 */ 00064 cfg_val = irq104[ irq ] & ~0x20; 00065 cfg_val = ( cfg_val << bit ) | enable; 00066 cfg_mask = ( 7 << bit ) | enable; 00067 cfg_word = ( in16( 0x312 ) & ~cfg_mask ) | cfg_val; 00068 nl_error( -2, "SC104 writing CPA word %04X", cfg_word ); 00069 out16( 0x312, cfg_word ); 00070 } 00071 return iid; 00072 } 00073 00074 static void int_reset( int iid, unsigned short mask ) { 00075 if ( iid != -1 ) InterruptDetach( iid ); 00076 if ( subbus_subfunction == SB_SYSCON104 ) { 00077 unsigned short cfg_word = ( in16( 0x312 ) & ~mask ); 00078 out16( 0x312, cfg_word ); 00079 } 00080 } 00081 00082 void expint_init( int coid, short code, int value ) { 00083 expint_iid = int_init( expint_irq, 0x20, 0, coid, code, value ); 00084 } 00085 00086 void expint_reset(void) { 00087 int_reset( expint_iid, 0x3F ); 00088 } 00089 00090 void expint_svc(void) { 00091 service_expint(NULL,0,0,NULL); 00092 InterruptUnmask( expint_irq, expint_iid ); 00093 } 00094 00095 #ifdef IRQ_SUPPORT 00096 static int spare_iid = -1; 00097 static int pfail_iid = -1; 00098 int spare_irq = 0; 00099 int pfail_irq = 0; 00100 00101 void spare_init( void ) { 00102 spare_iid = int_init( spare_irq, 0x2000, 10, spare_handler ); 00103 } 00104 00105 void spare_reset( void ) { 00106 int_reset( spare_iid, 0x3C00 ); 00107 } 00108 00109 void pfail_init( void ) { 00110 if ( pfail_proxy == 0 ) { 00111 pfail_proxy = qnx_proxy_attach( 0, NULL, 0, -1 ); 00112 outp( 0x316, 0); /* reset the lowpower signal */ 00113 if ( pfail_proxy == -1 ) 00114 nl_error( 3, "Unable to attach proxy for pfail" ); 00115 pfail_iid = int_init( pfail_irq, 0x200, 6, pfail_handler ); 00116 } 00117 } 00118 00119 void pfail_reset( void ) { 00120 int_reset( pfail_iid, 0x3C0 ); 00121 set_failure(1); 00122 if ( qnx_proxy_detach( pfail_proxy ) ) { 00123 nl_error(1, "Error detaching pfail_proxy"); 00124 } 00125 pfail_proxy = 0; 00126 } 00127 #endif