ARPDAS_QNX6 1.0
|
00001 /* expint.c Provides all the specific code to handle support for 00002 the expints 00003 00004 Registration is done with Region, cardID and a bit number is 00005 assigned. Need to be able to detach based on cardID, need to 00006 be able to trigger based on region and bit 00007 00008 When a pulse arrives, go through our list of regions. 00009 For each region, read the INTA and compare the result to the 00010 bits we've defined. If any are active, search through the list 00011 of programs that have registered on that bit and Trigger the 00012 appropriate pulse or pulses. 00013 */ 00014 #include <stdlib.h> 00015 #include <errno.h> 00016 #include <string.h> 00017 #include <signal.h> 00018 #include "nortlib.h" 00019 #include "subbusd_int.h" 00020 00021 // typedef struct { 00022 // unsigned short address; 00023 // unsigned short bits; 00024 // card_def *def[8]; 00025 // } region; 00026 // #define MAX_REGIONS 4 00027 00028 card_def *carddefs; 00029 region regions[ MAX_REGIONS ]; 00030 00031 static void delete_card( card_def **cdp ) { 00032 card_def *cd; 00033 00034 if ( cdp == 0 || *cdp == 0 ) 00035 nl_error( 4, "Invalid pointer to delete_card" ); 00036 cd = *cdp; 00037 regions[ cd->reg_id ].def[ cd->bitno ] = NULL; 00038 regions[ cd->reg_id ].bits &= ~(1 << cd->bitno ); 00039 *cdp = cd->next; 00040 free( cd ); 00041 } 00042 00043 static card_def **find_card( char *cardID, unsigned short address ) { 00044 card_def *cd, **cdp; 00045 00046 for ( cdp = &carddefs, cd = carddefs; 00047 cd != 0; 00048 cdp = &cd->next, cd = cd->next ) { 00049 if ( strncmp( cd->cardID, cardID, CardID_MAX ) == 0 00050 || cd->address == address ) { 00051 return cdp; 00052 } 00053 } 00054 return NULL; 00055 } 00056 00057 /** 00058 * @return On success, returns zero and sets *card to new card_def. errno codes on failure. 00059 */ 00060 int expint_attach( int rcvid, char *cardID, unsigned short address, 00061 int region, struct sigevent *event, card_def **card ) { 00062 card_def **cdp, *cd; 00063 int bitno, bit, i; 00064 00065 /* Verify that the region is legal */ 00066 if ( ( region & (~6) ) != 0x40 || address == 0 ) { 00067 nl_error( 1, 00068 "Illegal region (0x%02X) or address (0x%03X) requested", 00069 region, address ); 00070 return ENXIO; 00071 } 00072 00073 /* First check to make sure it isn't already defined */ 00074 cdp = find_card( cardID, address ); 00075 if ( cdp != 0 ) { 00076 cd = *cdp; 00077 if ( cd->address != address ) { 00078 nl_error( 2, "Same ID (%s) two addresses (0x%03X, 0x%03X)", 00079 cardID, cd->address, address ); 00080 return ENXIO; 00081 } else { 00082 // I used to check if the former owner was still alive. 00083 // I will use the implicit close() operation to 00084 // delete interrupt. 00085 nl_error( 1, "Duplicate request for cardID %s", cardID ); 00086 return EAGAIN; 00087 } 00088 } 00089 00090 /* set up the region and select the bit */ 00091 for ( i = 0; i < MAX_REGIONS && regions[i].address != 0; i++ ) { 00092 if ( regions[i].address == region ) break; 00093 } 00094 if ( i == MAX_REGIONS ) { 00095 nl_error( 2, "Too many regions requested!" ); 00096 return ENOSPC; 00097 } 00098 regions[i].address = region; 00099 for ( bitno = 0, bit = 1; bitno < 8; bitno++, bit <<= 1 ) { 00100 if ( ( regions[i].bits & bit ) == 0 ) break; 00101 } 00102 //* Note that 8 is an arbitrary limitation of Syscon104. 00103 //* Nonetheless, we are unlikely to hit it with any architecture. 00104 if ( bitno == 8 ) { 00105 nl_error( 2, "Too many requests for region 0x%02X", region ); 00106 return ENOSPC; 00107 } 00108 00109 /* Now assign a new def. */ 00110 cd = malloc( sizeof( card_def ) ); 00111 if ( cd == 0 ) { 00112 nl_error( 2, "Out of memory in expint_attach" ); 00113 return ENOMEM; 00114 } 00115 strncpy( cd->cardID, cardID, CardID_MAX ); 00116 cd->cardID[ CardID_MAX - 1 ] = '\0'; 00117 cd->address = address; 00118 cd->reg_id = i; 00119 cd->bitno = bitno; 00120 cd->event = *event; 00121 cd->owner = rcvid; 00122 nl_error(-2,"expint_att %s 0x%03X reg=%d bit=%d", 00123 cd->cardID, cd->address, cd->reg_id, cd->bitno ); 00124 00125 regions[i].bits |= bit; 00126 regions[i].def[bitno] = cd; 00127 00128 cd->next = carddefs; 00129 carddefs = cd; 00130 *card = cd; 00131 return EOK; 00132 } 00133 00134 int expint_detach( int rcvid, char *cardID, unsigned short *addr, unsigned int *bn ) { 00135 card_def **cdp; 00136 00137 cdp = find_card( cardID, 0 ); 00138 if ( cdp == 0 ) { 00139 return ENOENT; 00140 } else if ( (*cdp)->owner != rcvid ) { 00141 nl_error( 1, "Non-owner %d attempted detach for %s", 00142 rcvid, cardID ); 00143 return EPERM; 00144 } else { 00145 *addr = (*cdp)->address; 00146 *bn = (*cdp)->bitno; 00147 delete_card( cdp ); 00148 return EOK; 00149 } 00150 }