ARPDAS_QNX6 1.0
|
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 }