ARPDAS_QNX6 1.0
expint.c
Go to the documentation of this file.
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 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines