ARPDAS_QNX6 1.0
sc104.c
Go to the documentation of this file.
00001 /* sc104.c
00002  * subbusd module to interface directly to Syscon/104
00003  */
00004 #include <stdio.h>
00005 #include <string.h>
00006 #include <sys/neutrino.h>
00007 #include <hw/inout.h>
00008 #include <errno.h>
00009 #include "subbusd_int.h"
00010 #include "nortlib.h"
00011 #include "sc104.h"
00012 #include "nl_assert.h"
00013 
00014 unsigned short subbus_version = SUBBUS_VERSION;
00015 unsigned short subbus_features = SUBBUS_FEATURES;
00016 unsigned short subbus_subfunction = LIBRARY_SUB;
00017 
00018 #if SC104
00019 int read_ack( unsigned short addr, unsigned short *data ) {
00020   int i, status;
00021   out16(SC_SB_LOWB, addr); // Output address
00022   out8(SC_SB_LOWC, 1); // assert read
00023   for ( i = WAIT_COUNT; i > 0; i-- ) {
00024     status = in16(SC_SB_LOWC); // Check read+write bit
00025     if ( !(status | 0x800) ) break;
00026   }
00027   *data = in16(SC_SB_LOWA);
00028   return((status&0x40) ? i+1 : 0 );
00029 }
00030 #endif
00031 
00032 unsigned short sbrb(unsigned short addr) {
00033   unsigned short word;
00034 
00035   read_ack(addr, &word);
00036   if (addr & 1) word >>= 8;
00037   return(word & 0xFF);
00038 }
00039 
00040 
00041 #if SC104
00042 int write_ack(unsigned short addr, unsigned short data) {
00043   int i, status;
00044   out16(SC_SB_LOWB, addr); // Output address
00045   out16(SC_SB_LOWA, data); // Output data
00046   for ( i = WAIT_COUNT; i > 0; i-- ) {
00047     status = in16(SC_SB_LOWC);
00048     if ( !(status & 0x800) ) break;
00049   }
00050   return ((status&0x40) ? i+1 : 0 );
00051 }
00052 #endif
00053 
00054 /** don't need to serialize access to cmdenbl, since it's I/O port mapped.
00055  */
00056 int set_cmdenbl(int val) {
00057   out16(SC_CMDENBL, val);
00058   return 0;
00059 }
00060 
00061 /**
00062  * Function to set cmdstrobe value.
00063  * @param val non-zero value asserts cmdstrobe.
00064  * @return non-zero no success, zero if operation is not supported.
00065  *
00066  *  Function did not exist at all before version 3.10, so
00067  *  programs intending to use this function should verify that
00068  *  the resident library version is at least 3.10. The feature
00069  *  word can also be checked for support, and that is consistent
00070  *  back to previous versions.
00071  */
00072 int set_cmdstrobe(int value) {
00073   #if SYSCON
00074     #if SC104
00075       out8(SC_SB_LOWC, 8 | (value?0:2));
00076     #else
00077       out8(SC_SB_LOWCTRL, 2 | (value?1:0));
00078     #endif
00079     return 1;
00080   #else
00081     return 0;
00082   #endif
00083 }
00084 
00085 unsigned short read_switches(void) {
00086   #if READSWITCH
00087     return in8(SC_SWITCHES) | 0x8000;
00088   #else
00089     return 0x8000;
00090   #endif
00091 }
00092 
00093 int set_failure(unsigned short value) {
00094   #if SIC
00095     if ( value ) in8(SC_LAMP);
00096     else out8(SC_LAMP,0);
00097   #endif
00098   #if SYSCON
00099     out8(SC_LAMP,value);
00100   #endif
00101   return 0;
00102 }
00103 
00104 unsigned short read_failure(void) {
00105   #if SYSCON
00106     return in8(SC_LAMP);
00107   #else
00108     return 0;
00109   #endif
00110 }
00111 
00112 int tick_sic(void) {
00113   out8(SC_TICK, 0);
00114   return 0;
00115 }
00116 
00117 int disarm_sic(void) {
00118   out8(SC_DISARM, 0);
00119   return 0;
00120 }
00121 
00122 static void ErrorReply( int rcvid, int rv ) {
00123   subbusd_rep_hdr_t rep;
00124   nl_assert( rv > 0 );
00125   rep.status = -rv;
00126   rep.ret_type = SBRT_NONE;
00127   rv = MsgReply( rcvid, sizeof(rep), &rep, sizeof(rep) );
00128 }
00129 
00130 /**
00131  The basic sanity of the incoming message has been
00132  checked by subbus_io_msg before it gets here,
00133  so we can at least assume that the message was
00134  big enough to include the specified message type,
00135  and that the message type is defined.
00136  */
00137 void incoming_sbreq( int rcvid, subbusd_req_t *req ) {
00138   subbusd_rep_t rep;
00139   int rsize, rv;
00140   
00141   rep.hdr.status = SBS_OK;
00142   rep.hdr.ret_type = SBRT_US;
00143 
00144   switch ( req->sbhdr.command ) {
00145     case SBC_READACK:
00146       rep.hdr.status =
00147         read_ack( req->data.d1.data, &rep.data.value ) ?
00148         SBS_ACK : SBS_NOACK;
00149       break;
00150     case SBC_READCACHE:
00151       rep.hdr.status =
00152         (sb_cache_read(req->data.d1.data, &rep.data.value) < 0) ?
00153         SBS_NOACK : SBS_ACK;
00154       break;
00155     case SBC_WRITECACHE:
00156       rv = sb_cache_write(req->data.d0.address, req->data.d0.data);
00157       if (rv != 1) {
00158         rep.hdr.ret_type = SBRT_NONE;
00159         rep.hdr.status = (rv == 0) ? SBS_ACK : SBS_NOACK;
00160         break;
00161       }
00162       /* else fall through */
00163     case SBC_WRITEACK:
00164       rep.hdr.status =
00165         write_ack( req->data.d0.address, req->data.d0.data ) ?
00166         SBS_ACK : SBS_NOACK;
00167       rep.hdr.ret_type = SBRT_NONE;
00168       break;
00169     case SBC_SETCMDENBL:
00170       set_cmdenbl(req->data.d1.data);
00171       rep.hdr.ret_type = SBRT_NONE;
00172       break;
00173     case SBC_SETCMDSTRB:
00174       set_cmdstrobe( req->data.d1.data );
00175       rep.hdr.ret_type = SBRT_NONE;
00176       break;
00177     case SBC_SETFAIL:
00178       set_failure(req->data.d1.data);
00179       rep.hdr.ret_type = SBRT_NONE;
00180       break;
00181     case SBC_READSW:
00182       rep.data.value = read_switches();
00183       break;
00184     case SBC_READFAIL:
00185       rep.data.value = read_failure();
00186       break;
00187     case SBC_GETCAPS:
00188       rep.data.capabilities.subfunc = LIBRARY_SUB;
00189       rep.data.capabilities.features = SUBBUS_FEATURES;
00190       strncpy(rep.data.capabilities.name,
00191           "Subbus Library V4.00: Syscon/104",
00192           SUBBUS_NAME_MAX );
00193       rep.hdr.ret_type = SBRT_CAP;
00194       break;
00195     case SBC_TICK:
00196       tick_sic();
00197       rep.hdr.ret_type = SBRT_NONE;
00198       break;
00199     case SBC_DISARM:
00200       disarm_sic();
00201       rep.hdr.ret_type = SBRT_NONE;
00202       break;
00203     case SBC_INTATT:
00204       rv = int_attach(rcvid, req);
00205       if (rv != EOK) {
00206         ErrorReply(rcvid, rv);
00207         return;
00208       }
00209       break;
00210     case SBC_INTDET:
00211       rv = int_detach(rcvid, req);
00212       if (rv != EOK) {
00213         ErrorReply(rcvid, rv);
00214         return;
00215       }
00216       break;
00217     case SBC_QUIT:
00218       rep.hdr.ret_type = SBRT_NONE;
00219       break;
00220     default:
00221       nl_error(4, "Undefined command in incoming_sbreq!" );
00222   }
00223   switch (rep.hdr.ret_type) {
00224     case SBRT_NONE: rsize = sizeof(subbusd_rep_hdr_t); break;
00225     case SBRT_US: rsize =
00226         sizeof(subbusd_rep_hdr_t) + sizeof(unsigned short);
00227       break;
00228     case SBRT_CAP:
00229       rsize = sizeof(subbusd_rep_hdr_t) + sizeof(subbusd_cap_t);
00230       break;
00231     default:
00232       rsize = sizeof(subbusd_rep_t);
00233       break;
00234   }
00235   rv = MsgReply( rcvid, rsize, &rep, rsize );
00236 }
00237 
00238 void init_subbus(dispatch_t *dpp ) {
00239   int expint_pulse;
00240   
00241   if (ThreadCtl(_NTO_TCTL_IO,0) == -1 )
00242     nl_error( 3, "Error requesting I/O priveleges: %s", strerror(errno) );
00243   // We won't do mmap_device_io()
00244   // http://www.qnx.com/developers/articles/article_304_2.html
00245   out16( SC_SB_RESET, 0 );
00246   #if !SC104
00247     #if SYSCON
00248       out16( SC_SB_LOWCTRL, SC_SB_CONFIG );
00249     #else
00250       out8( SC_SB_LOWCTRL, SC_SB_CONFIG & 0xFF );
00251       out8( SC_SB_HIGHCTRL, (SC_SB_CONFIG >> 8) & 0xFF );
00252     #endif
00253   #endif
00254   expint_pulse =
00255     pulse_attach(dpp, MSG_FLAG_ALLOC_PULSE, 0, service_expint, NULL);
00256   expint_init(message_connect(dpp, MSG_FLAG_SIDE_CHANNEL),
00257       expint_pulse, 0 );
00258 }
00259 
00260 void shutdown_subbus(void) {
00261   nl_error( 0, "Shutting down" );
00262 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines