00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <locale.h>
00034 #include <libintl.h>
00035
00036
00037 #include "glbvars.h"
00038 #include "plug-ins/hard/modules/dsp.h"
00039 #include <fcntl.h>
00040 #include <sys/ioctl.h>
00041
00042 #include "dsp-pci32/xsm/dpramdef.h"
00043 #include "dsp-pci32/xsm/xsmcmd.h"
00044
00045 #include "innovative_dsp_hwi.h"
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 innovative_dsp_hwi_dev::innovative_dsp_hwi_dev(int ver):XSM_Hardware(){
00058 EventCheckOn();
00059
00060 dsp_cmd = open(xsmres.DSPDev, O_RDWR);
00061 dsp_usr = open(xsmres.DSPDev, O_RDWR);
00062 dsp_data = open(xsmres.DSPDev, O_RDWR);
00063 if(dsp_cmd <= 0){
00064 printf("open %s failed, err=%d\nPlease do \"insmod pci32, pc31, ccd, dspspaemu or dspbbspa...\" (you need root for this) !\n\n"
00065 "Or if you want to go without hardware, you can temporary disable hardware access:\n use: \"gxsm -h no\"\n",
00066 xsmres.DSPDev, dsp_cmd);
00067 exit(0);
00068 }
00069 if(dsp_data <= 0 || dsp_usr <= 0){
00070 printf("second open %s failed, err=%d\nsorry, something goes wrong !\n", xsmres.DSPDev, dsp_data);
00071 close(dsp_cmd);
00072 exit(0);
00073 }
00074
00075 switch(ioctl(dsp_cmd, PCDSP_GETMODID)){
00076 case PCDSP_MODID_SIM: InfoString = g_strdup("Module is SIM"); break;
00077 case PCDSP_MODID_PC31: InfoString = g_strdup("Module is PC31"); break;
00078 case PCDSP_MODID_PCI32: InfoString = g_strdup("Module is PCI32"); break;
00079 default:
00080 InfoString = g_strdup("Module Typ is unknown!");
00081 }
00082
00083 ioctl(dsp_cmd, PCDSP_SEM1START, DSP_CTRL_REGION);
00084 ioctl(dsp_cmd, PCDSP_SEM1LEN, DSP_CTRL_REG_LEN);
00085
00086 ioctl(dsp_usr, PCDSP_SEM2START, DSP_USR_REGION);
00087 ioctl(dsp_usr, PCDSP_SEM2LEN, DSP_USR_REG_LEN);
00088
00089 ioctl(dsp_data, PCDSP_SEM3START, DSP_DATA_REGION);
00090 ioctl(dsp_data, PCDSP_SEM3LEN, DSP_DATA_REG_LEN);
00091
00092 lseek(dsp_cmd, BYTSIZE(DSP_CTRL_REGION), SEEK_SET);
00093 lseek(dsp_usr, BYTSIZE(DSP_USR_REGION), SEEK_SET);
00094 lseek(dsp_data, BYTSIZE(DSP_DATA_REGION), SEEK_SET);
00095
00096 in_use_count=0;
00097
00098
00099 g_free(get_DSP_softinfo ());
00100 }
00101
00102
00103
00104
00105
00106 innovative_dsp_hwi_dev::~innovative_dsp_hwi_dev(){
00107 close(dsp_cmd);
00108 close(dsp_usr);
00109 close(dsp_data);
00110 }
00111
00112 void innovative_dsp_hwi_dev::ExecCmd(int Cmd){
00113 unsigned long dspctrl, l;
00114 clock_t timeout;
00115 dspctrl = (unsigned long)Cmd;
00116
00117 if(write(dsp_cmd, &dspctrl, BYTSIZE(DSP_CTRL_PARAM)))
00118 XSM_SHOW_ALERT(N_("Attention"), N_("ExecCmd: DSP write failed!"), " ", 0);
00119
00120 timeout=clock()+DSP_TIMEOUT*CLOCKS_PER_SEC;
00121 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_WRITE_NOWAIT, dspctrl)) && timeout > clock())
00122 gapp->check_events();
00123 if(!l)
00124 XSM_SHOW_ALERT(N_("Attention"), N_("ExecCmd: Timeout, DSP write mbox failed!"), " ", 0);
00125 }
00126
00127 int innovative_dsp_hwi_dev::WaitExec(int data){
00128 return 0;
00129 }
00130
00131 void innovative_dsp_hwi_dev::Evchk(){ gapp->check_events(); usleep(5000); };
00132
00133 void innovative_dsp_hwi_dev::NoEvchk(){ usleep(5000); };
00134
00135
00136
00137 void innovative_dsp_hwi_dev::SetParameter(PARAMETER_SET &hps, int scanflg){
00138 static clock_t last_error_time = 0;
00139 static int error_count = 0;
00140 static int errmsg_disable = 0;
00141 #define CHECK_ERR_DTIME { \
00142 if (last_error_time+5 > clock()) errmsg_disable = 1;\
00143 if (++error_count > 20) errmsg_disable = 1;\
00144 last_error_time = clock(); \
00145 }
00146 #define SHOW_MSG(A,B) { \
00147 if (errmsg_disable) \
00148 std::cerr << "innovative_dsp_hwi_dev::SetParameter Error Message: (to many, redirected to console)" << std::endl \
00149 << "-- " << A << std::endl \
00150 << "-- " << B << std::endl; \
00151 else \
00152 gapp->alert (N_("Attention"), A, B, 0); \
00153 }
00154 clock_t timeout;
00155 unsigned long l;
00156 unsigned long dspctrl[DSP_CTRL_REG_LEN];
00157 union fl { float f; unsigned long hl; } Fl;
00158
00159 static int busy=0;
00160 XSM_DEBUG (DBG_L2, "Calling instance #"<< busy <<" of SetParameter.");
00161 busy++;
00162
00163 int k=0;
00164 while (busy > 1) {
00165 usleep (50000);
00166 if (k==0)
00167 XSM_DEBUG (DBG_L2, "SetParameter is busy [" << busy << "] - waiting.");
00168 if (++k > 20){
00169 XSM_DEBUG (DBG_L2, "-- Giving up waiting on DSP and trying to force setting parameters. Releasing Mutex "<< busy<<" --");
00170 --busy;
00171 break;
00172 }
00173 }
00174
00175 dspctrl[DSP_CTRL_CMD] = (unsigned long)hps.Cmd;
00176 for(int i=0; i<hps.N; i++){
00177 Fl.f = hps.hp[i].value;
00178 dspctrl[i + DSP_CTRL_PARAM] = Fl.hl;
00179 }
00180
00181
00182 timeout=clock()+DSP_TIMEOUT*CLOCKS_PER_SEC;
00183
00184
00185 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_EMPTY, FALSE)) && timeout > clock())
00186 (*EventCheck)();
00187
00188
00189 if(write(dsp_cmd, dspctrl, BYTSIZE(hps.N+DSP_CTRL_PARAM))){
00190 CHECK_ERR_DTIME;
00191 SHOW_MSG (N_("DSP write parameters failed !"),
00192 N_("cause: error while writing to device.")
00193 );
00194 }
00195
00196
00197 if(scanflg){
00198 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_WRITE_NOWAIT, hps.Cmd)) && timeout > clock())
00199 (*EventCheck)();
00200 if(!l){
00201 CHECK_ERR_DTIME;
00202 SHOW_MSG (N_("SetParameter: DSP write mbox failed."),
00203 N_("cause: timeout, in scan, cmd=PCDSP_MBOX_WRITE_NOWAIT"));
00204 }
00205
00206
00207 CallIdleFunc();
00208
00209
00210
00211 int k=0;
00212 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_EMPTY, FALSE)) && timeout > clock()){
00213 if(k-- >= 0)
00214 NoEvchk();
00215 else
00216 (*EventCheck)();
00217
00218 if(KillFlg){
00219 XSM_DEBUG (DBG_L2, "Release Mutex "<<busy<<" due to KillFlag set.");
00220 --busy;
00221 }
00222 return;
00223 }
00224 }else{
00225 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_WRITE_NOWAIT, hps.Cmd)) && timeout > clock())
00226 Evchk();
00227 if(!l){
00228 CHECK_ERR_DTIME;
00229 SHOW_MSG (N_("SetParameter: DSP write mbox failed."),
00230 N_("cause: timeout, no scan"));
00231 }
00232
00233 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_EMPTY, FALSE)) && timeout > clock())
00234 Evchk();
00235 }
00236 if(!l){
00237 gchar *tt=g_strdup_printf("timeout=%ds reached: waiting since %gs",
00238 DSP_TIMEOUT, (double)((clock()-timeout)/CLOCKS_PER_SEC));
00239 CHECK_ERR_DTIME;
00240 SHOW_MSG (N_("SetParameter: DSP wait for mbox empty failed. \n"
00241 "-- cause: timeout; write data and cmd exec OK"),
00242 tt);
00243 g_free(tt);
00244 }
00245 XSM_DEBUG (DBG_L2, "Release Mutex " <<busy<<" due to end of function call");
00246 --busy;
00247 }
00248
00249
00250 void innovative_dsp_hwi_dev::GetParameter(PARAMETER_SET &hps){
00251 unsigned long dspctrl[DSP_CTRL_REG_LEN];
00252 union fl { float f; unsigned long hl; } Fl;
00253
00254
00255 if(read(dsp_cmd, dspctrl, BYTSIZE(hps.N+DSP_CTRL_PARAM)))
00256 gapp->alert("Achtung", "DSP read parameters failed !", " ", 0);
00257
00258 for(int i=0; i<hps.N; i++){
00259 Fl.hl = dspctrl[i + DSP_CTRL_PARAM];
00260 hps.hp[i].value = Fl.f;
00261 }
00262 }
00263
00264 gchar* innovative_dsp_hwi_dev::get_DSP_softinfo (){
00265 PARAMETER_SET hardpar;
00266 #define TMPSIZE 1000
00267 gchar infotxt[TMPSIZE+1];
00268 int i;
00269
00270 scan_data_mode = SCAN_DATA_SWAP_SHORT;
00271 prb_data_mode = PRB_SHORT;
00272 max_points_per_line = DSP_DATA_REG_LEN<<1;
00273
00274 XSM_DEBUG (DBG_L2, "innovative_dsp_hwi_dev::get_DSP_softinfo -- Asking DSP to report software info." );
00275
00276 hardpar.N = 1;
00277 hardpar.Cmd = DSP_CMD_GETINFO;
00278 hardpar.hp[0].value = 0.;
00279 SetParameter(hardpar, FALSE);
00280
00281 long infobuffer[DSP_DATA_REG_LEN];
00282
00283
00284 ReadData(infobuffer, DSP_DATA_REG_LEN*sizeof(long));
00285
00286 memset (infotxt, 0, sizeof(infotxt));
00287
00288 if (!strncmp ((char*)infobuffer, "*123-567-9abXdef", 16)){
00289 XSM_DEBUG(DBG_L2, "++ KERNEL-EMU-DETECTED" );
00290 strcpy (infotxt,
00291 "*--XSM-DSP-SOFT-INFO--*\n"
00292 "--*Kernel-Emu-Detected*--\n");
00293 memcpy ((void*)&infotxt[strlen(infotxt)], (void*)&infobuffer[92/4],
00294 MIN ((strlen ((char*)&infobuffer[92/4])-1), (TMPSIZE-100)));
00295 }else{
00296 XSM_DEBUG(DBG_L2, "-- DSP-W-LONGMODE-DPRAM-SUGGESTED" );
00297 for(i=0; i<TMPSIZE && infobuffer[i]!='@'; ++i)
00298 infotxt[i] = (gchar)infobuffer[i];
00299 infotxt[i]=0;
00300 }
00301 if (strncmp (infotxt, "*--XSM-DSP-SOFT-INFO--*", 23)){
00302 XSM_DEBUG(DBG_L2, "-- AUTOMATIC DEVICE IDENTIFY FAILED" );
00303 infobuffer[24] = 0;
00304 gchar *tmp = g_strdup_printf ("Sorry, this DSP software does not support reports!\n"
00305 "Identify String found:\n"
00306 "<%s>\n",
00307 (char*)infobuffer);
00308 XSM_DEBUG_PLAIN (DBG_L2, tmp);
00309 return (tmp);
00310 }
00311 XSM_DEBUG(DBG_L2, "++ AUTOMATIC DEVICE IDENTIFY OK, REPORT:" );
00312 XSM_DEBUG_PLAIN (DBG_L2, infotxt );
00313 XSM_DEBUG(DBG_L2, "** END OF REPORT" );
00314
00315
00316 if (strstr (infotxt, "ProbeDataMode: short")){
00317 prb_data_mode = PRB_SHORT;
00318 XSM_DEBUG(DBG_L2, "DSP ProbeData Mode is SHORT." );
00319 } else if (strstr (infotxt, "ProbeDataMode: float")){
00320 prb_data_mode = PRB_FLOAT;
00321 XSM_DEBUG(DBG_L2, "DSP ProbeData Mode is FLOAT." );
00322 } else
00323 XSM_DEBUG(DBG_L2, "DSP ProbeData Mode not reported, using SHORT." );
00324
00325 if (strstr (infotxt, "DPRAMDATAMOVE: yes")){
00326 scan_data_mode = SCAN_DATA_MOVE2DPRAM_SHORT;
00327 XSM_DEBUG(DBG_L2, "Scan Data Mode is MOVE2DPRAM." );
00328 } else if (strstr (infotxt, "DPRAMSWAP: yes")){
00329 scan_data_mode = SCAN_DATA_SWAP_SHORT;
00330 XSM_DEBUG(DBG_L2, "Scan Data Mode is SWAP (deprecated mode)." );
00331 } else
00332 XSM_DEBUG(DBG_L2, "Scan Data ModeDSP not reported, using old SWAP method." );
00333
00334 gchar *dpl;
00335 if ((dpl = strstr (infotxt, "DATABUFFERLEN: "))){
00336 max_points_per_line = atoi (dpl + 15)<<1;
00337 XSM_DEBUG(DBG_L2, "Found DATABUFFERLEN, setting max points per line to " << max_points_per_line );
00338 }
00339
00340 return (g_strdup (infotxt));
00341 }
00342
00343 size_t innovative_dsp_hwi_dev::ReadData(void *buf, size_t count) {
00344
00345 return read(dsp_data, buf, count);
00346 }
00347
00348 int innovative_dsp_hwi_dev::ReadScanData(int y_index, int num_srcs, Mem2d *m[MAX_SRCS_CHANNELS]){
00349 int len = m[0]->GetNx();
00350 if (scan_data_mode == SCAN_DATA_MOVE2DPRAM_SHORT){
00351 if( len & 1 ) ++len;
00352 int mv_buf_len = len*num_srcs;
00353 if (y_index == -1)
00354 mv_buf_len *= m[0]->GetNy();
00355 int dataset_len = mv_buf_len;
00356 if (mv_buf_len > (DSP_DATA_REG_LEN<<1))
00357 mv_buf_len = (DSP_DATA_REG_LEN<<1);
00358 SHT *linebuffer = new SHT[dataset_len];
00359
00360 int mv_len = mv_buf_len;
00361 int offset = 0;
00362 do{
00363 ReadData (&linebuffer[offset], mv_len*sizeof(SHT));
00364 offset += mv_buf_len;
00365 if (offset < dataset_len){
00366 PARAMETER_SET hardpar;
00367 hardpar.N = DSP_LSSRCS+1;
00368 hardpar.Cmd = DSP_CMD_MOVE_DATA2DPRAM;
00369 hardpar.hp[DSP_MVD_CMD_START].value = offset>>1;
00370 hardpar.hp[DSP_MVD_CMD_LEN ].value = (mv_len = ((dataset_len-offset) > mv_buf_len
00371 ? mv_buf_len : dataset_len-offset)) >> 1;
00372 SetParameter (hardpar, TRUE);
00373 } else break;
00374 }while (1);
00375
00376 int y = y_index == -1 ? 0:y_index;
00377 for (int offset=0; y < m[0]->GetNy(); ++y){
00378 for (int i=0; i<num_srcs; ++i)
00379 if (m[i])
00380 m[i]->PutDataLine (y, linebuffer+ i*len + offset);
00381 if (y_index == -1)
00382 offset += len*num_srcs;
00383 else
00384 break;
00385 }
00386
00387 delete[] linebuffer;
00388 }else{
00389 if (y_index < 0) return 0;
00390
00391 SHT linebuffer[DSP_DATA_REG_LEN<<1];
00392 size_t elem_size=sizeof(SHT);
00393 size_t bsz = (len*elem_size);
00394 int i = 0;
00395 int n = 0;
00396 do{
00397 size_t sz = 0;
00398 int bin = 0;
00399 while (n < num_srcs && (sz+bsz) < (DSP_DATA_REG_LEN<<2)){
00400 sz += bsz;
00401 ++n;
00402 ++bin;
00403 }
00404 if (sz > 0){
00405
00406 ReadData(linebuffer, sz);
00407 int j = 0;
00408 do{
00409 m[i++]->PutDataLine (y_index, linebuffer+(j++)*len);
00410 }while(--bin && (i < MAX_SRCS_CHANNELS) ? m[i] != NULL : FALSE);
00411 }
00412 else
00413 break;
00414
00415 ExecCmd(DSP_CMD_SWAPDPRAM);
00416 }while ((i < MAX_SRCS_CHANNELS) ? m[i]!=NULL : FALSE);
00417 }
00418 return 0;
00419 }
00420
00421 int innovative_dsp_hwi_dev::ReadProbeData(int nsrcs, int nprobe, int kx, int ky, Mem2d *m, double scale){
00422 if (prb_data_mode == PRB_SHORT){
00423 size_t data_set_size = nprobe * nsrcs * sizeof(SHT);
00424 if (data_set_size >= (DSP_DATA_REG_LEN<<2))
00425 return 0;
00426 SHT linebuffer[DSP_DATA_REG_LEN<<1];
00427 ReadData(linebuffer, data_set_size);
00428
00429 if (kx == -1 && ky == -1)
00430 for (int i=0; i < nsrcs; ++i)
00431 for (int k=0; k < nprobe; ++k)
00432 m->PutDataPkt (((double)linebuffer[k+i*nprobe]) * scale,
00433 k, i);
00434 else
00435 for (int k=0; k < nprobe; ++k)
00436 m->PutDataPkt (((double)linebuffer[k]) * scale,
00437 kx, ky, k);
00438 return 1;
00439
00440 } else if (prb_data_mode == PRB_FLOAT){
00441 size_t data_set_size = nprobe * nsrcs * sizeof(float);
00442 if (data_set_size >= (DSP_DATA_REG_LEN<<2))
00443 return 0;
00444 float linebuffer[DSP_DATA_REG_LEN<<2];
00445 ReadData(linebuffer, data_set_size);
00446
00447 if (kx == -1 && ky == -1)
00448 for (int i=0; i < nsrcs; ++i)
00449 for (int k=0; k < nprobe; ++k)
00450 m->PutDataPkt (((double)linebuffer[k+i*nprobe]) * scale,
00451 k, i);
00452 else
00453 for (int k=0; k < nprobe; ++k)
00454 m->PutDataPkt (((double)linebuffer[k]) * scale,
00455 kx, ky, k);
00456 return 1;
00457 } else return 0;
00458 }
00459
00460
00461
00462