示例#1
0
static int copy_disk(CBM_FILE fd_cbm, imgcopy_settings *settings,
              const transfer_funcs *src, const void *src_arg,
              const transfer_funcs *dst, const void *dst_arg, unsigned char cbm_drive)
{
	unsigned char tr = 0;
	unsigned char se = 0;
	int st;
	int cnt  = 0;
	unsigned char scnt = 0;
	unsigned char errors;
	int retry_count;
	int resend_trackmap;
	char trackmap[MAX_SECTORS+1];
	char buf[40];
	//unsigned const char *bam_ptr;
	unsigned char bam[BLOCKSIZE *5];
	int bam_count;
	unsigned char block[BLOCKSIZE];
	//unsigned char gcr[GCRBUFSIZE];
	const transfer_funcs *cbm_transf = NULL;
	imgcopy_status status;
	const char *type_str = "*unknown*";


	if(settings->drive_type == cbm_dt_unknown )
	{
		message_cb( 2, "Trying to identify drive type" );
		if( cbm_identify( fd_cbm, cbm_drive, &settings->drive_type, NULL ) )
		{
			message_cb( 0, "could not identify device" );
		}

		switch( settings->drive_type )
		{
		    case cbm_dt_cbm1541:
		    case cbm_dt_cbm1570:
		    case cbm_dt_cbm1571:
		    case cbm_dt_cbm4040:
		        message_cb( 0, "drive is not supported" );
		        return -1;
		    case cbm_dt_cbm1581:
		    case cbm_dt_cbm8050:
		    case cbm_dt_cbm8250:
		    case cbm_dt_sfd1001:
		        /* fine */
		        break;
		    default:
		        message_cb( 1, "Unknown drive, assuming 8250" );
		        settings->drive_type = cbm_dt_cbm8250;
		        break;
		}
	}

	if(settings->two_sided == -1)
	{
		// set default
		switch( settings->drive_type )
		{
		   case cbm_dt_cbm8250:
		   case cbm_dt_sfd1001:
			settings->two_sided = 1;
			break;
		   case cbm_dt_cbm8050:
		   case cbm_dt_cbm1581:
		   default:
			settings->two_sided = 0;
			break;
		}
	}
	if(imgcopy_set_image_type(settings, NULL))
	{
		message_cb(0, "invalid imagetype for this drive type");
		return -1;
	}
	if(imgcopy_sector_count(settings, 1) < 0)
	{
		message_cb(0, "invalid drive or image type");
		return -1;
	}


	if(settings->interleave != -1 &&
	       (settings->interleave < 1 || settings->interleave > 24))
	{
		message_cb(0,
		        "invalid value (%d) for interleave", settings->interleave);
		return -1;
	}

	if(settings->start_track < 1 || settings->start_track > settings->max_tracks)
	{
	    message_cb(0,
	            "invalid value (%d) for start track. (MAXTRACKS=%d)", settings->start_track, settings->max_tracks);
	    return -1;
	}

	if(settings->end_track != -1 && 
	   (settings->end_track < settings->start_track ||
	    settings->end_track > settings->max_tracks))
	{
	    message_cb(0,
	            "invalid value (%d) for end track. (MAXTRACKS=%d)", settings->end_track, settings->max_tracks);
	    return -1;
	}

	if(settings->interleave == -1)
	{
		switch( settings->drive_type )
		{
		   case cbm_dt_cbm1581:
			settings->interleave = 1;				// always 1 cause track buffering
			break;
		   case cbm_dt_cbm8050:
		   case cbm_dt_cbm8250:
		   case cbm_dt_sfd1001:
		   default:
			settings->interleave = (dst->is_cbm_drive && settings->warp) ?
			    warp_write_interleave[settings->transfer_mode] :
			    default_interleave[settings->transfer_mode];
			break;
		}
		assert(settings->interleave >= 0);
	}

	SETSTATEDEBUG((void)0);
	cbm_exec_command(fd_cbm, cbm_drive, "I0:", 0);
	SETSTATEDEBUG((void)0);
	cnt = cbm_device_status(fd_cbm, cbm_drive, buf, sizeof(buf));
	SETSTATEDEBUG((void)0);

	switch( settings->drive_type )
	{
	    case cbm_dt_cbm8050: 	type_str = "CBM-8050"; break;
	    case cbm_dt_cbm8250: 	type_str = "CBM-8250"; break;
	    case cbm_dt_sfd1001:		type_str = "SFD-1001"; break;
	    case cbm_dt_cbm1581:	type_str = "CBM-1581"; break; 
	    default: 					type_str = "unknown"; break; 
	}

	if(cnt == 66)
	{
		// illegal track or sector :: DOS error
		if(settings->image_type == D80)
			cnt = 0;
		else
		{
			if(settings->image_type == D82)
			{
				//settings->image_type = D80;
				//imgcopy_set_image_type(settings, NULL);

				message_cb(1, "maybe a 8050 disk in a 8250 drive");
				cnt = 0;
			}
		}
	}
	if(cnt)
	{
		// DOS error
		message_cb(0, "drive %02d (%s): %s", cbm_drive, type_str, buf );
		return -1;
	}
	message_cb(2, "drive %02d (%s)", cbm_drive, type_str);


	if(settings->two_sided)
	{
		switch( settings->drive_type )
		{
		    case cbm_dt_cbm8250:
		    case cbm_dt_sfd1001:
			// ok
			break;
		    default:
			message_cb(0, "requires a two side drive");
			return -1;
		}
		SETSTATEDEBUG((void)0);
	}

	switch( settings->drive_type )
	{
	    case cbm_dt_cbm1541:
	    case cbm_dt_cbm1571:
		if(settings->warp && (cbm_transf->read_gcr_block == NULL))
		{
		    if(settings->warp>0)
		        message_cb(1, "`-w' for this transfer mode ignored");
		    settings->warp = 0;
		}
		break;

	    case cbm_dt_cbm1581:
	    case cbm_dt_cbm8050:
	    case cbm_dt_cbm8250:
	    case cbm_dt_sfd1001:
	    default:
	        if(settings->warp)
	        {
	            if(settings->warp>0)
	                message_cb(1, "drive type doesn't support warp mode");
	            	settings->warp = 0;
	        }
		break;
	}

	//
	// Check if transfer mode is allowed
	//
 	if(imgcopy_check_transfer_mode(settings))
	{
	    message_cb(0, "transfer mode not allowed for this drive type");
	    return -1;
	}

	message_cb(2, "set transfer struc.");
	SETSTATEDEBUG((void)0);
	cbm_transf = src->is_cbm_drive ? src : dst;


	settings->warp = settings->warp ? 1 : 0;

	if(cbm_transf->needs_turbo)
	{
		int rc;
		message_cb(2, "sending turbo drive code ...");
		SETSTATEDEBUG((void)0);
//		send_turbo(fd_cbm, cbm_drive, dst->is_cbm_drive, settings->warp, settings->drive_type == cbm_dt_cbm1541 ? 0 : 1);
		if((rc=send_turbo(settings, fd_cbm, cbm_drive, dst->is_cbm_drive)) != 0)
		{
		    message_cb(0, "error while upload of drive code (rc=%d)", rc);
		    return -1;
		}
	}


	SETSTATEDEBUG((void)0);
	message_cb(2, "open source disk.");
	if(src->open_disk(fd_cbm, settings, src_arg, 0,
	                  start_turbo, message_cb) == 0)
	{
		if(settings->end_track == -1)
		{
			settings->end_track = settings->max_tracks;
		}
		SETSTATEDEBUG((void)0);
		message_cb(2, "open destination.");
		if(dst->open_disk(fd_cbm, settings, dst_arg, 1,
		                  start_turbo, message_cb) != 0)
		{
			message_cb(0, "can't open destination");
			return -1;
		}
	}
	else
	{
	    message_cb(0, "can't open source");
	    return -1;
	}

	//message_cb(2, "set BAM buffer (%dx%d)", MAX_TRACKS, MAX_SECTORS);
	memset(status.bam, bs_invalid, MAX_TRACKS * MAX_SECTORS);

	if(settings->bam_mode != bm_ignore)
	{
		//message_cb(2, "reading BAM ...");
		st = ReadBAM(settings, src, bam, &bam_count);
		if(st)
		{
			message_cb(1, "failed to read BAM (%d), reading whole disk", st);
			settings->bam_mode = bm_ignore;
		}
	}
	SETSTATEDEBUG((void)0);

	memset(&status, 0, sizeof(status));

	/* setup BAM */
	//message_cb(3, "setup BAM (%d tracks)", settings->max_tracks);
	for(tr = 1; tr <= settings->max_tracks; tr++)
	{
		int sectorCount = imgcopy_sector_count(settings, tr);

		//message_cb(2, "track %d, sector %d", tr,  sectorCount);

		if(tr < settings->start_track || tr > settings->end_track)
		{
		    memset(status.bam[tr-1], bs_dont_copy, sectorCount);
		}
		else if(settings->bam_mode == bm_allocated ||
		        (settings->bam_mode == bm_save && (tr != settings->cat_track && tr != settings->bam_track )))
		{
			//message_cb(2, "offsets into BAM for track: tr=%d, se=%d", tr);
			/*char lbuf[100];
			gets(lbuf);*/
			for(se = 0; se < sectorCount; se++)
			{
				if(ChkBAM(settings, bam, tr, se))
				{
					//printf("copy track: %d, sector: %d\n", tr, se);
					status.bam[tr-1][se] = bs_must_copy;
					status.total_sectors++;
				}
				else
				{
					//printf("don't copy track: %d, sector: %d\n", tr, se);
					status.bam[tr-1][se] = bs_dont_copy;
				}
			}
		}
		else
		{
		    status.total_sectors += sectorCount;
		    memset(status.bam[tr-1], bs_must_copy, sectorCount);
		}
	}

	status.settings = settings;

	status_cb(status);

	message_cb(2, "copying tracks %d-%d (%d sectors)",
	        settings->start_track, settings->end_track, status.total_sectors);


	//
	// copy disk
	//
	SETSTATEDEBUG(debugLibImgBlockCount=0);
	for(tr = 1; tr <= settings->max_tracks; tr++)
	{
		unsigned char sectorCount = (unsigned char) imgcopy_sector_count(settings, tr);

		if(tr >= settings->start_track && tr <= settings->end_track)
		{
			memcpy(trackmap, status.bam[tr-1], sectorCount);
			retry_count = settings->retries;
			do
			{
				errors = resend_trackmap = 0;

				// calc count of blocks to copy
				scnt = sectorCount;
				if(settings->bam_mode != bm_ignore)
				{
				    for(se = 0; se < sectorCount; se++)
				    {
				        if(trackmap[se] != bs_must_copy)
				        {
				            scnt--;
				        }
				    }
				}
				//if(tr == 77)  printf("scnt=%d\n", scnt);

				if(scnt > 0 && settings->warp && src->is_cbm_drive)
				{
				    SETSTATEDEBUG((void)0);
				    src->send_track_map(settings, tr, trackmap, scnt);
				}
				else
				{
				    se = 0;
				}
				while(scnt > 0 && !resend_trackmap)
				{
					/* if(settings->warp && src->is_cbm_drive)
					{
						SETSTATEDEBUG((void)0);
						status.read_result = src->read_gcr_block(&se, gcr);
						if(status.read_result == 0)
						{
						    SETSTATEDEBUG((void)0);
						    status.read_result = gcr_decode(gcr, block);
						}
						else
						{
						    // mark all sectors not received so far 
						    // ugly 
						    errors = 0;
						    for(scnt = 0; scnt < sector_map[tr]; scnt++)
						    {
						        if(NEED_SECTOR(trackmap[scnt]) && scnt != se)
						        {
						            trackmap[scnt] = bs_error;
						            errors++;
						        }
						    }
						    resend_trackmap = 1;
						}
					}
					else */
					{
						int se_max = sectorCount;

						while(!NEED_SECTOR(trackmap[se]))
						{
						    if(++se >= sectorCount) se = 0;
						    if(se_max-- <= 0)	break;
						}
						if(se_max-- <= 0)	break;

						SETSTATEDEBUG(debugLibImgBlockCount++);
						status.read_result = src->read_block(tr, se, block);
					}

					/*if(settings->warp && dst->is_cbm_drive)
					{
					    SETSTATEDEBUG((void)0);
					    gcr_encode(block, gcr);
					    SETSTATEDEBUG(debugLibImgBlockCount++);
					    status.write_result = 
					        dst->write_block(tr, se, gcr, GCRBUFSIZE-1,
					                         status.read_result);
					}
					else  */
					{
					    SETSTATEDEBUG(debugLibImgBlockCount++);
					    status.write_result = 
					        dst->write_block(tr, se, block, BLOCKSIZE,
					                         status.read_result);
					}
					SETSTATEDEBUG((void)0);

					if(status.read_result)
					{
					    /* read error */
					    trackmap[se] = bs_error;
					    errors++;
					    if(retry_count == 0)
					    {
					        status.sectors_processed++;
					        /* FIXME: shall we get rid of this? */
					        message_cb( 1, "read error: %02x/%02x: %d",
					                    tr, se, status.read_result );
					    }
					}
					else
					{
					    /* successfull read */
					    if(status.write_result)
					    {
					        /* write error */
					        trackmap[se] = bs_error;
					        errors++;
					        if(retry_count == 0)
					        {
					            status.sectors_processed++;
					            /* FIXME: shall we get rid of this? */
					            message_cb(1, "write error: %02x/%02x: %d",
					                       tr, se, status.write_result);
					        }
					    }
					    else
					    {
					        /* successfull read and write, mark sector */
					        trackmap[se] = bs_copied;
					        cnt++;
					        status.sectors_processed++;
					    }
					}
					/* remaining sectors on this track */
					if(!resend_trackmap)
					{
					    scnt--;
					}

					status.track = tr;
					status.sector= se;
					status_cb(status);

					if(dst->is_cbm_drive || !settings->warp)
					{
						se += (unsigned char) settings->interleave;
						if(se >= sectorCount) se -= sectorCount;
					}
				}
				//if(tr == 77)  printf("after while\n");

				if(errors > 0)
				{
					retry_count--;
					scnt = errors;
				}
			} while(retry_count >= 0 && errors > 0);

			//if(tr == 77)  printf("after do\n");

			if(errors)
			{
				message_cb(1, "giving up...");
			}
		}

		if(settings->two_sided)
		{
			if(tr <= D80_TRACKS)
			{
				if(tr + D80_TRACKS <= D82_TRACKS)
				{
				    tr += (D80_TRACKS -1);
				}
			}
			else if(tr != D82_TRACKS)
			{
				tr -= D80_TRACKS;
			}
		}
		//message_cb(2, "track: %d, maxtrack=%d", tr, settings->max_tracks);
	}
	message_cb(2, "finished imagecopy.");

	SETSTATEDEBUG(debugLibImgBlockCount=-1);


	dst->close_disk();
	SETSTATEDEBUG((void)0);
	src->close_disk();

	SETSTATEDEBUG((void)0);
	return cnt;
}
示例#2
0
int ARCH_MAINDECL
main(int argc, char **argv)
{
    unsigned char drive = 8;
    int i;
    unsigned char cmd[] = "M-R\x87\x00\x02";
    static unsigned char rpm_prog[] =
    {
#include "rpm1541.inc"
    };

    unsigned long  int count;
    unsigned short int currpm, tsize;
    struct
    {
      unsigned short int rpm;
      unsigned short int occurence;
    } occtable[OCCSZ];
    const char *type_str;


    if (cbm_driver_open_ex(&fd, NULL) != 0)
        return -1;

    if (argc > 1)
    {
      drive = arch_atoc(argv[1]);

      if (drive < 8 || drive > 11)
      {
          printf("Usage: %s [driveNo]\n\ndriveNo  - Commodore IEC bus"
                 " disk drive number (range: 8..11)\n", argv[0]);
          exit(0);
      }
    }
    if (cbm_identify(fd, drive, NULL, &type_str) == 0)
    {
        printf( "Using drive %2d, drive type string: %s\n", drive, type_str );
    }

    arch_set_ctrlbreak_handler(reset);

    cbm_exec_command(fd, drive, "I0:", 0);
    cbm_upload(fd, drive, 0x0500, rpm_prog, sizeof(rpm_prog));

    count = 1ul;
    tsize = 0;
    for (i = 0; i < OCCSZ; ++i)
    {
        occtable[i].rpm=occtable[i].occurence=0;
    }

    while (1)
    {
        unsigned char int_count[2];
        double rpm;

        cbm_exec_command(fd, drive, "U4:", 0);
        cbm_exec_command(fd, drive, cmd, sizeof(cmd)-1);
        cbm_talk(fd, drive, 15);
        cbm_raw_read(fd, &int_count, 2);
        cbm_untalk(fd);

        rpm = (600000.0*RUNS) / (int_count[0] + 256 * int_count[1]);

/*      printf("%3.2lf\n", rpm); */
        currpm = (unsigned short int)(rpm*100 + .5);  /* rounded! */

        /* search occurency table for that value */
        for (i=0;i<OCCSZ;++i)
        {
            if (occtable[i].rpm == 0)
            {
                /* value not found, but an empty field */
                break;
            }
            else if (currpm == occtable[i].rpm)
            {
                /* value found, increase counter */
                occtable[i].occurence++;
                break;
            }
        }

        if (i >= OCCSZ || occtable[i].rpm==0)
        {
            if (i >= OCCSZ)
            {
                printf("\rNo space left in occurrency table for rpm value %3.2f\n", rpm);
            }
            else /* if (occtable[i].rpm==0) */
            {
                occtable[i].rpm=currpm;
                occtable[i].occurence++;
            }

            /* reprint table header either if the overflow warning
             * was printed or a new rpm value has been added
             */
            printf("\r%10s: %6s", "count", "curRPM");
            for (i = 0; i < OCCSZ && occtable[i].rpm != 0; ++i)
            {
                printf("|%3.2f", occtable[i].rpm / 100.0);
            }
            printf("|\n------------------");
            for (i=0;i<OCCSZ && occtable[i].rpm!=0;++i)
            {
                printf("+------");
            }
            printf("+\n");
        }

        printf("\r%10lu: %3.2f", count++, rpm);
        for (i=0;i<OCCSZ && occtable[i].rpm!=0;++i)
        {
            printf("|%6u", occtable[i].occurence);
        }
        printf("|");
        fflush(stdout);
        /* printf("%10lu: %3.2f %5u\n", count++, rpm, currpm); */
    }

    return 0;
}
示例#3
0
//
// stgart drive code at $0503
//
static int start_turbo(CBM_FILE fd, unsigned char drive)
{
    SETSTATEDEBUG((void)0);
    return cbm_exec_command(fd, drive, "U4:", 3);
}
示例#4
0
int ARCH_MAINDECL main(int argc, char *argv[])
{
    int status = 0, id_ofs = 0, name_len, i;
    CBM_FILE fd;
//    unsigned char drive, tracks = 35, bump = 1, orig = 0, show_progress = 0;
    unsigned char drive, tracks = 35, bump = 1, orig = 0x4b, show_progress = 0;
    char cmd[40], name[20], *arg;
    int erroroccured = 0;
    char *adapter = NULL;
    int option;

    struct option longopts[] =
    {
        { "help"       , no_argument      , NULL, 'h' },
        { "version"    , no_argument      , NULL, 'V' },
        { "adapter"    , required_argument, NULL, '@' },
        { "no-bump"    , no_argument      , NULL, 'n' },
        { "extended"   , no_argument      , NULL, 'x' },
//        { "original"   , no_argument      , NULL, 'o' },
{ "fill"  , required_argument, NULL, 'f' },

        { "status"     , no_argument      , NULL, 's' },
        { "progress"   , no_argument      , NULL, 'p' },

        /* undocumented */
        { "end-track"  , required_argument, NULL, 't' },
        { NULL         , 0                , NULL, 0   }
    };

//    const char shortopts[] ="hVnxospt:";
    const char shortopts[] ="hVnxf:spt:";


    while((option = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
    {
        switch(option)
        {
            case 'n': bump = 0;
                      break;
            case 'f': //orig = 0x4b;
orig=arch_atoc(optarg);
                      break;
            case 's': status = 1;
                      break;
            case 'x': tracks = 40;
                      break;
            case 'h': help();
                      return 0;
            case 'V': printf("frm_analyzer %s\n", OPENCBM_VERSION);
                      return 0;
            case 'p': show_progress = 1;
                      break;
            case 't': tracks = arch_atoc(optarg);
                      break;
            case '@': if (adapter == NULL)
                          adapter = cbmlibmisc_strdup(optarg);
                      else
                      {
                          fprintf(stderr, "--adapter/-@ given more than once.");
                          hint(argv[0]);
                          return 1;
                      }
                      break;
            default : hint(argv[0]);
                      return 1;
        }
    }

    if(optind + 2 != argc)
    {
        fprintf(stderr, "Usage: %s [OPTION]... DRIVE NAME,ID\n", argv[0]);
        hint(argv[0]);
        return 1;
    }

    arg = argv[optind++];
    drive = arch_atoc(arg);
    if(drive < 8 || drive > 11)
    {
        fprintf(stderr, "Invalid drive number (%s)\n", arg);
        return 1;
    }
    
    arg      = argv[optind++];
    name_len = 0;
    while(*arg)
    {
        unsigned char c;
        c = (unsigned char) toupper(*arg);
        if(c == ',')
        {
            if(id_ofs)
            {
                fprintf(stderr, "More than one `,' in disk name\n");
                return 1;
            }
            id_ofs = name_len;
        }
        name[name_len++] = c;
        if(name_len > 19)
        {
            fprintf(stderr, "Disk name too long\n");
            return 1;
        }
        arg++;
    }
    name[name_len] = 0;

    if(cbm_driver_open_ex(&fd, adapter) == 0)
    {
        cbm_upload(fd, drive, 0x0300, dskfrmt, sizeof(dskfrmt));
        sprintf(cmd, "M-E%c%c%c%c%c%c0:%s", 3, 3, tracks + 1, 
                orig, bump, show_progress, name);
        cbm_exec_command(fd, drive, cmd, 11+strlen(name));
#if 0
        if(show_progress)
        {
            /* do some handshake */
            cbm_iec_release(fd, IEC_CLOCK);
            for(i = 1; i <= tracks; i++)
            {
                cbm_iec_wait(fd, IEC_DATA, 1);
                cbm_iec_set(fd, IEC_CLOCK);
                cbm_iec_wait(fd, IEC_DATA, 0);
                cbm_iec_release(fd, IEC_CLOCK);

                printf("#");
                fflush(stdout);
            }
            printf("\n");
        }
#endif
        erroroccured = cbm_device_status(fd, drive, cmd, sizeof(cmd));

        if(erroroccured && status)
        {
            printf("%s\n", cmd);
        }

        if(!erroroccured && (tracks > 35))
        {
            cbm_open(fd, drive, 2, "#", 1);
            cbm_exec_command(fd, drive, "U1:2 0 18 0", 11);
            cbm_exec_command(fd, drive, "B-P2 192", 8);
            cbm_listen(fd, drive, 2);
            while(tracks > 35)
            {
                cbm_raw_write(fd, "\021\377\377\001", 4);
                tracks--;
            }
            cbm_unlisten(fd);
            cbm_exec_command(fd, drive, "U2:2 0 18 0", 11);
            cbm_close(fd, drive, 2);
        }

        if(!erroroccured && status)
        {
            cbm_device_status(fd, drive, cmd, sizeof(cmd));
            printf("%s\n", cmd);
        }
#if 1   // verbose output
        {
#if 0 // @TODO unused variables
            float RPMval;
            int sectors, virtGAPsze, remainder, trackTailGAP, flags, retry, lastTr;
            const char *vrfy;
#endif
            unsigned char data[0x100];
            if (cbm_download(fd, drive, 0x0500, data, sizeof(data)) == sizeof(data))
            {


#if 1
                // TODO, Pattern analyzer, get the lenght of the PLL synchronization period
                //
                    // search the last byte triple consisting of: 0x49, 0x24, 0x92
                    // 
                int k;
                const unsigned char pattern[]={0x49, 0x24, 0x92};
                // const unsigned char pattern[]={0xdb, 0x6d, 0xb6};

                for(k=sizeof(data)-3; k>=0; --k)
                {
                    if(data[k]==pattern[0] && data[k+1]==pattern[1] && data[k+2]==pattern[2]) break;
                }
                if(k<0)
                {
                    // no part of the written sequence was found
                    k=sizeof(data);
                }
                else
                {    
                        // now search the beginning of that "010010010010010010010010..." bit stream
                    while(k>=0 && data[k]==pattern[0] && data[k+1]==pattern[1] && data[k+2]==pattern[2])
                    {
                        k-=3;
                    }
                    k+=3;
    
                        // do single byte decreases
                    if(k>=1 && data[k-1]==pattern[2]) --k;
                    if(k>=1 && data[k-1]==pattern[1]) --k;
                    if(k>=1 && data[k-1]==pattern[0]) --k;
                }

                printf("Result with Pattern: 0x%02X / %3d, formatted on track %2d, PLL synchronization length: %3d\n", orig, orig, tracks, k);


                for (i=0; i < sizeof(data); i++)
                {
                    /*
                    if(data[i] == 0)
                    {
                        printf("\n");
                        break;
                    }
                    */
                    printf(" %02X", data[i]);
                    if((i&0x0f) == 0x0f) printf("\n");
                }
#else
                int i;
                printf("Track|Retry|sctrs|slctd|| GAP |modulo |modulo|tail| Verify  | RPM  |\n"
                       "     |     |     | GAP ||adjst|complmt| dvsr |GAP |         |      |\n"
                       "-----+-----+-----+-----++-----+-------+------+----+---------+------+\n");

                lastTr=-1;
                for (i=0; i < sizeof(data); i+=4)
                {
                    if(data[i]==0) break;    // no more data is available


                    if(data[i+3]>=0x40 && data[i]>42){
                            // logging continuation line
                        printf("     |     | debug log || $%02X | $%02X $%02X $%02X\n",
                               data[i], data[i+1], data[i+2], data[i+3]);
                        continue;    // proceed with next loop run
                        }


                    if(data[i]==lastTr) retry++;
                    else                retry=0;
                    lastTr=data[i];

                    if(data[i]>=25)            // preselect track dependent constants
                    {
                        if(data[i]>=31) sectors=17, RPMval=60000000.0f/16;
                        else            sectors=18, RPMval=60000000.0f/15;
                    }
                    else
                    {
                        if(data[i]>=18) sectors=19, RPMval=60000000.0f/14;
                        else            sectors=21, RPMval=60000000.0f/13;
                    }

                        // separate some flags
                    flags=(data[i+3]>>6)&0x03;
                    data[i+3]&=0x3f;

                    switch(flags)
                    {
                        case 0x01: vrfy="SYNC fail"; break;
                        case 0x02: vrfy="verify OK"; break;
                        case 0x03: vrfy="vrfy fail"; break;
                        default:   vrfy="   ./.   ";
                    }

                        // recalculation of the track tail GAP out of the
                        // choosen GAP for this track, the new GAP size
                        // adjustment and the complement of the remainder
                        // of the adjustment division

                    virtGAPsze=data[i+1]         -3;    // virtual GAP increase to
                        // prevent reformatting, when only one byte is missing


                    remainder=((data[i+2]==0xff) ? virtGAPsze : sectors)
                                 - data[i+3];


                    trackTailGAP=((data[i+2]==0xff) ? 0 : data[i+2]*sectors + virtGAPsze)
                                    + remainder;

                        // the following constants are nybble based (double the
                        // size of the well known constants for SYNC lengths,
                        // block header size, data block GAP and data block)
                        //
                        // (0x01&data[i+1]&sectors) is a correction term, if "half
                        // GAPs" are written and the number of sectors is odd
                        //
                    // RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]&sectors) + trackTailGAP - data[i+1])

                    RPMval = (flags != 0x01) ?
                        RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]&sectors) + trackTailGAP - data[i+1])
                        : 0;

                    printf(" %3u | ", data[i]);
                    if(retry>0) printf("%3u", retry);
                    else        printf("   ");
                   /*      " |sctrs |slctd  || GAP   |modulo   |modulo  |tail | Verify  | RPM  |\n"
                    *      " |      | GAP   ||adjst  |complmt  |        |GAP  |         |      |\n"
                    *      "-+----- +-----  ++-----  +-------  +------  +---- +---------+------+\n"
                    */
                    printf(" |  %2u | $%02X || $%02X |   $%02X |  $%02X |$%03X|%9s|%6.2f|\n",
                           sectors, data[i+1], data[i+2], data[i+3],
                           remainder, trackTailGAP, vrfy, RPMval);
                }
                printf("\n  *) Note: All GAP based numbers shown here (sedecimal values) are\n"
                         "           nybble based (4 GCR Bits) instead of GCR byte based.\n");
#endif
            }
            else
            {
示例#5
0
int main(int argc, char **argv)
{
    int ret, n;
    unsigned char drive = 8;
    CBM_FILE f;
    char buffer[80];
    char *devicetype_str;
    const char *drivername;
    enum cbm_device_type_e devicetype;
    int checklines = 0;
    int checkiohook = 0;

    if (argc>1)
    {
        int i;

        for (i=0; i < argc; i++)
        {
            switch (argv[i][0])
            {
            case '-':
                    checklines = 1;
                    break;

            case '+':
                    checkiohook = 1;
                    break;

            default:
                    drive = atoi(argv[i]);
            }
        }
    }

    printf("VDDTEST " __DATE__ " " __TIME__ ", using drive %u\n", drive);

    if (vdd_init())
    {
        printf("Could not initialize the VDD, aborting!\n");
        exit(1);
    }

    drivername = cbm_get_driver_name(0);
    printf("cbm_get_driver_name() returned %s.\n", drivername);

    ret = cbm_driver_open(&f, 0);

    if (ret)
    {
        printf("cbm_driver_open FAILED!\n");
        exit(1);
    }
    printf("cbm_driver_open success!\n\n");

    n = cbm_reset(f);
    printf("cbm_reset %s\n", n==0 ? "success" : "FAILED");

    if (checklines)
    {
        changelines(f);
    }

    n = cbm_device_status(f, drive, buffer, sizeof(buffer));
    printf("cbm_device_status returned: %u\n%s\n\n", n, buffer);

    n = cbm_open(f, drive, 15, "I0", 0);
    printf("cbm_open %u,15,\"I0\" %s!\n", drive, n == 0 ? "success" : "FAILED");
    n = cbm_close(f, drive, 15);
    printf("cbm_close %s!\n", n == 0 ? "success" : "FAILED");

    n = own_device_status(f, drive, buffer, sizeof(buffer));
    printf("own_device_status returned: %u\n%s\n\n", n, buffer);

    n = cbm_identify(f, drive, &devicetype, &devicetype_str);
    printf("cbm_identify %s!\n", n==0 ? "success" : "FAILED");
    printf("cbm_identify returned: %u - '%s'.\n\n", (unsigned int) devicetype,
                         devicetype_str);

    n = cbm_exec_command(f, drive, "S0:OPENCBM.VDD", 0);
    printf("cbm_exec_command(scratch) %s!\n", n==0 ? "success" : "FAILED");

    writefile(f, drive, "OPENCBM.VDD,S,W");
    readfile(f, drive, "OPENCBM.VDD,S,R");

    morse(f, drive);

    if (checkiohook)
    {
        unsigned int base = 0x0fc0;

        printf("trying to install iohook at 0x%08x ", base);
        if (vdd_install_iohook(f, base, 1))
        {
            int i;

            printf("success\n");

            for (i=0; i<15; i++)
            {
                outportb(base + 2, i);
                sleep(1);
            }

            printf("trying to uninstall iohook ");
            if (vdd_uninstall_iohook(f))
            {
                printf("success\n");
            }
            else
            {
                printf("FAILED\n");
            }
        }
        else
        {
            printf("FAILED\n");
        }
    }

    cbm_driver_close(f);
    printf("cbm_driver_close success!\n");

    return 0;
}
示例#6
0
int ARCH_MAINDECL main(int argc, char *argv[])
{
    int status = 0, id_ofs = 0, name_len;
    CBM_FILE fd;
    unsigned char drive, starttrack = 1, endtrack = 35, bump = 1, orig = 0;
    unsigned char verify = 0, demagnetize = 0, retries = 7;
    char cmd[40], name[20], *arg;
    struct FormatParameters parmBlock;
    int berror = 0;
    char *adapter = NULL;
    int option;

    struct option longopts[] =
    {
        { "help"       , no_argument      , NULL, 'h' },
        { "version"    , no_argument      , NULL, 'V' },
        { "adapter"    , required_argument, NULL, '@' },
        { "no-bump"    , no_argument      , NULL, 'n' },
        { "extended"   , no_argument      , NULL, 'x' },
        { "original"   , no_argument      , NULL, 'o' },
        { "status"     , no_argument      , NULL, 's' },
        { "verify"     , no_argument      , NULL, 'v' },
        { "clear"      , no_argument      , NULL, 'c' },
        { "retries"    , required_argument, NULL, 'r' },

        /* undocumented */
        { "fillpattern", required_argument, NULL, 'f' },
        { "begin-track", required_argument, NULL, 'b' },
        { "end-track"  , required_argument, NULL, 'e' },
        { NULL         , 0                , NULL, 0   }
    };

    const char shortopts[] ="hVnxosvcr:f:b:e:@:";

    while((option = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
    {
        switch(option)
        {
            case 'n': bump = 0;
                      break;
            case 'o': orig = 0x4b;
                      break;
            case 's': status = 1;
                      break;
            case 'x': starttrack =  1;
                      endtrack   = 40;
                      break;
            case 'h': help();
                      return 0;
#ifdef CBMFORNG
            case 'V': printf("cbmforng %s\n", OPENCBM_VERSION);
#else
            case 'V': printf("cbmformat %s\n", OPENCBM_VERSION);
#endif
                      return 0;
            case 'v': verify = 1;
                      break;
            case 'c': demagnetize = 1;
                      break;
            case 'r': retries = arch_atoc(optarg);
                      if(retries<1)       retries= 1;
                      else if(retries>63) retries=63;
                      break;

            case 'f': orig = arch_atoc(optarg);
                      break;
            case 'b': starttrack = arch_atoc(optarg);
                      break;
            case 'e': endtrack = arch_atoc(optarg);
                      break;
            case '@': if (adapter == NULL)
                          adapter = cbmlibmisc_strdup(optarg);
                      else
                      {
                          fprintf(stderr, "--adapter/-@ given more than once.");
                          hint(argv[0]);
                          return 1;
                      }
                      break;
            default : hint(argv[0]);
                      return 1;
        }
    }

    if(optind + 2 != argc)
    {
        fprintf(stderr, "Usage: %s [OPTION]... DRIVE NAME,ID\n", argv[0]);
        hint(argv[0]);
        return 1;
    }

    arg = argv[optind++];
    drive = arch_atoc(arg);
    if(drive < 8 || drive > 11)
    {
        fprintf(stderr, "Invalid drive number (%s)\n", arg);
        return 1;
    }
    
    arg      = argv[optind++];
    name_len = 0;
    while(*arg)
    {
        unsigned char c;
        c = (unsigned char) toupper(*arg);
        if(c == ',')
        {
            if(id_ofs)
            {
                fprintf(stderr, "More than one `,' in disk name\n");
                return 1;
            }
            id_ofs = name_len;
        }
        name[name_len++] = c;
        if(name_len > 19)
        {
            fprintf(stderr, "Disk name too long\n");
            return 1;
        }
        arg++;
    }
    name[name_len] = 0;

    if(name_len - id_ofs != 3)
    {
        fprintf(stderr, "Missing `,' in disk name or ID field not equal to two characters\n");
        return 1;
    }

    if(cbm_driver_open_ex(&fd, adapter) == 0)
    {
        cbm_upload(fd, drive, 0x0300, dskfrmt, sizeof(dskfrmt));


        prepareFmtPattern(&parmBlock, orig, endtrack, name[id_ofs+1], name[id_ofs+2]);
        parmBlock.P_STRCK=starttrack;   // start track parameter
        parmBlock.P_ETRCK=endtrack+1;   // end track parameter
        parmBlock.P_RETRY=(retries & ~0xC0) | (bump?0x40:0xC0);
                                        // number of retries (per disk, not per track)
        parmBlock.P_DOBMP=bump;         // flag, if an initial head bump should be done
        parmBlock.P_DEMAG=demagnetize;  // flag, if the disk should be demagnetized
        parmBlock.P_VRIFY=verify;       // flag, if the disk should be verified

#if 0       // for checking the generated format patterns
{
    int j,k;
    for(j=0;j<34;j+=5)
    {
        for(k=0;k<5;k++)
        {
            printf(" $%02X", ((char *)(&parmBlock))[j+k]&0xFF);
        }
        printf("\n");
    }
    printf(" $%02X\n", ((char *)(&parmBlock))[j]&0xFF);
}
#endif
        cbm_upload(fd, drive, 0x0200 - sizeof(parmBlock), ((char *)(&parmBlock)), sizeof(parmBlock));

        sprintf(cmd, "M-E%c%c0:%s", 3, 3, name);
        cbm_exec_command(fd, drive, cmd, 7+name_len);
        berror = cbm_device_status(fd, drive, cmd, sizeof(cmd));

        if(berror && status)
        {
            printf("%s\n", cmd);
        }

#if defined(DebugFormat) && DebugFormat!=0  // verbose output
        {
            float RPMval;
            int sectors, virtGAPsze, remainder, trackTailGAP, flags, retry = 0, lastTr;
            const char *vrfy;
            unsigned char data[0x100];

                // in case of an error, get the logging buffer from 0x0700 instead of 0x0500
            if (cbm_download(fd, drive, berror?0x0700:0x0500, data, sizeof(data)) == sizeof(data))
            {
                int i;
                printf("Track|Retry|sctrs|slctd|| GAP |modulo |modulo|tail| Verify  | RPM  |\n"
                       "     |     |     | GAP ||adjst|complmt| dvsr |GAP |         |      |\n"
                       "-----+-----+-----+-----++-----+-------+------+----+---------+------+\n");

                lastTr=-1;
                for (i=0; i < sizeof(data); i+=4)
                {
                    if(data[i]==0) break;   // no more data is available

                    if(data[i]==lastTr) retry++;
                    else                retry=0;
                    lastTr=data[i];

                    if(data[i]>=25)         // preselect track dependent constants
                    {
                        if(data[i]>=31) sectors=17, RPMval=60000000.0f/16;
                        else            sectors=18, RPMval=60000000.0f/15;
                    }
                    else
                    {
                        if(data[i]>=18) sectors=19, RPMval=60000000.0f/14;
                        else            sectors=21, RPMval=60000000.0f/13;
                    }

                        // separate some flags
                    flags=(data[i+3]>>6)&0x03;
                    data[i+3]&=0x3f;

                    switch(flags)
                    {
                        case 0x01: vrfy="SYNC fail"; break;
                        case 0x02: vrfy="   OK    "; break;
                        case 0x03: vrfy="vrfy fail"; break;
                        default:   vrfy="   ./.   ";
                    }

                        // recalculation of the track tail GAP out of the
                        // choosen GAP for this track, the new GAP size
                        // adjustment and the complement of the remainder
                        // of the adjustment division

                    virtGAPsze=data[i+1]        -5; // virtual GAP increase to
                        // prevent reformatting, when only one byte is missing
                        // and other offset compensations


                    remainder=((data[i+2]==0xff) ? virtGAPsze : sectors)
                                 - data[i+3];


                    trackTailGAP=((data[i+2]==0xff) ? 0 : data[i+2]*sectors + virtGAPsze)
                                 + remainder;

                        // the following constants are nybble based (double the
                        // size of the well known constants for SYNC lengths,
                        // block header size, data block GAP and data block)
                        //
                        // (0x01&data[i+1]&sectors) is a correction term, if "half
                        // GAPs" are written and the number of sectors is odd
                        //
                    // RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]&sectors) + trackTailGAP - data[i+1])

                    RPMval = (flags != 0x01) ?
                        RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]&sectors) + trackTailGAP - data[i+1])
                        : 0;

                    printf(" %3u | ", data[i]);
                    if(retry>0) printf("%3u", retry);
                    else        printf("   ");

                   /*      " |sctrs |slctd   || GAP    |modulo    |modulo   |tail | Verify  | RPM  |\n"
                    *      " |      | GAP    ||adjst   |complmt   |         | GAP |         |      |\n"
                    *      "-+----- +-----   ++-----   +-------   +------   +---- +---------+------+\n"
                    */
                    printf(" |  %2u |$%02X.%d||$%02X.%d| $%02X.%d | $%02X.%d|$%03X|%9s|%6.2f|\n",
                           sectors,
                           data[i+1]>>1,                       (data[i+1]<<3)&8,            // selected GAP
                           (((signed char)data[i+2])>>1)&0xFF, (data[i+2]<<3)&8,            // GAP adjust
                           data[i+3]>>1,                       (data[i+3]<<3)&8,            // modulo complement
                           remainder>>1,                       (remainder<<3)&8,            // modulo
                           (trackTailGAP>>1) + 1,                                           // track tail GAP (with roundup)
                           vrfy, RPMval);
                }
                printf("\n  *) Note: The fractional parts of all the GAP based numbers shown here\n"
                         "           (sedecimal values) are given due to nybble based calculations.\n");
            }
            else
            {
示例#7
0
文件: cbmrpm41.c 项目: bogde/OpenCBM
int ARCH_MAINDECL
main(int argc, char *argv[])
{
    int status = 0;
    char cmd[40];
    unsigned char job = 1, begintrack = 1, endtrack = 35, retries = 5;
    char c, *arg;
    char *adapter = NULL;
    int sector = 0, berror = 0;

    struct option longopts[] =
    {
        { "help"       , no_argument      , NULL, 'h' },
        { "version"    , no_argument      , NULL, 'V' },
        { "adapter"    , required_argument, NULL, '@' },
        { "job"        , no_argument      , NULL, 'j' },
        { "retries"    , required_argument, NULL, 'r' },
        { "extended"   , no_argument      , NULL, 'x' },
        { "retries"    , required_argument, NULL, 'r' },
        { "begin-track", required_argument, NULL, 'b' },
        { "end-track"  , required_argument, NULL, 'e' },
        { "sector"     , required_argument, NULL, 'c' },
/*
        { "quiet"      , no_argument      , NULL, 'q' },
        { "verbose"    , no_argument      , NULL, 'v' },
        { "no-progress", no_argument      , NULL, 'n' },
*/
        { NULL         , 0                , NULL, 0   }
    };

    // const char shortopts[] ="hVj:sr:xb:e:c:qvn";
    const char shortopts[] ="hVj:sxr:b:e:c:@:";


    while((c=(unsigned char)getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
    {
        switch(c)
        {
            case 'h': help();
                      return 0;
            case 'V': printf("cbmrpm41 Version %s\n", OPENCBM_VERSION ", built on " __DATE__ " at " __TIME__ "\n");
                      return 0;
            case 'j': job = arch_atoc(optarg);
                      break;
            case 's': status = 1;
                      break;
            case 'x': begintrack = 1;
                      endtrack = 40;
                      break;

            case 'r': retries = arch_atoc(optarg);
                      if(retries<1)       retries =  1;
                      else if(retries>63) retries = 63;
                      break;
            case 'b': begintrack = arch_atoc(optarg);
                      break;
            case 'e': endtrack = arch_atoc(optarg);
                      break;
            case 'c': sector = atoi(optarg);
                      break;
            case '@': if (adapter == NULL)
                          adapter = cbmlibmisc_strdup(optarg);
                      else
                      {
                          fprintf(stderr, "--adapter/-@ given more than once.");
                          help();
                          return 0;
                      }
                      break;
            default : hint(argv[0]);
                      return 1;
        }
    }

    if(optind + 1 != argc)
    {
        fprintf(stderr, "Usage: %s [OPTION]... DRIVE\n", argv[0]);
        hint(argv[0]);
        return 1;
    }

    arg = argv[optind++];
    drive = arch_atoc(arg);
    if(drive < 8 || drive > 11)
    {
        fprintf(stderr, "Invalid drive number (%s)\n", arg);
        return 1;
    }
    if(begintrack < 1)
    {
        fprintf(stderr, "Beginning track is less than 1, it should be 1 or greater.\n");
        return 1;
    }
    if(endtrack > 42)
    {
        fprintf(stderr, "Ending track is greater than 42, it should be 42 or less.\n");
        return 1;
    }
    if(begintrack > endtrack)
    {
        fprintf(stderr, "Beginning track is greater than ending track, it should be less or equal.");
        return 1;
    }
    if(sector < 0)
    {
        fprintf(stderr, "Sector numbers less than zero are not allowed.");
        return 1;
    }


    SETSTATEDEBUG((void)0);
    printf("Please remove any diskettes used with production data on it. Insert a freshly\n"
           "formatted disk into drive %d; you can format a disk with e.g. the command:\n\n"
           "        cbmforng -o -v %d freshdisk,fd\n\n"
           "If you desperately need to examine a production disk or even an original\n"
           "diskette, then please protect the disk with a write protect adhesive label.\n\n"
           "Press <Enter>, when ready or press <CTRL>-C to abort.\r", drive, drive);
    getchar();

    if(cbm_driver_open_ex(&fd, adapter) == 0) do
    {
        arch_set_ctrlbreak_handler(handle_CTRL_C);

        SETSTATEDEBUG((void)0);
        if( cbm_upload(fd, drive, sizeof(cbmDev_StartAddress), cbmrpm41, sizeof(cbmrpm41))
            != sizeof(cbmrpm41)) break;

        // location of the new U vector user commands table
        sprintf(cmd, "%c%c", UcmdTblAddr & 0xFF, UcmdTblAddr >> 8);
        // install the new U vector table
        SETSTATEDEBUG((void)0);
        if( cbm_upload(fd, drive, sizeof(cbmDev_UxCMDtVector), cmd, 2)
            != 2) break;

        // execute Ux command behind the symbolic name Init23_BitTimersStd
        SETSTATEDEBUG((void)0);
        if( cbm_sendUxCommand(fd, drive, Init23_BitTimersStd)
            != 0) break;

        // read disk ID and initialise other parameters
        // from the currently inserted disk into the
        // drive's RAM locations
        SETSTATEDEBUG((void)0);
        if( cbm_exec_command(fd, drive, "I0", 2)
            != 0) break;

        SETSTATEDEBUG((void)0);
        berror = cbm_device_status(fd, drive, cmd, sizeof(cmd));
        if(berror && status)
        {
            printf("%s\n", cmd);
        }

        switch(job)
        {
        case 4:
            if( do_RPMadjustment (begintrack, endtrack, sector, retries)
                != 0 ) continue;    // jump to begin of do{}while(0);
            break;
        case 3:
            if( do_RPMregression (begintrack, endtrack, sector, retries)
                != 0 ) continue;    // jump to begin of do{}while(0);
            break;
        case 2:
            if( do_SKEWmeasurment(begintrack, endtrack, sector, retries)
                != 0 ) continue;    // jump to begin of do{}while(0);
            break;
        default:
            if( do_RPMmeasurment (begintrack, endtrack, sector, retries)
                != 0 ) continue;    // jump to begin of do{}while(0);
        }

        if( cbm_sendUxCommand(fd, drive, ResetVIA2ShiftRegConfig)
            != 0 ) break;
        if( cbm_sendUxCommand(fd, drive,      ResetUxVectorTable)
            != 0 ) break;

        if( cbm_exec_command(fd, drive, "I", 2)
            != 0 ) break;

        if(!berror && status)
        {
            cbm_device_status(fd, drive, cmd, sizeof(cmd));
            printf("%s\n", cmd);
        }
        cbm_driver_close(fd);
        cbmlibmisc_strfree(adapter);
        return 0;
    } while(0);
    else
    {
示例#8
0
文件: cbmrpm41.c 项目: bogde/OpenCBM
static int
measure_2cyleJitter(CBM_FILE HandleDevice, unsigned char DeviceAddress,
                    unsigned char diskTrack, unsigned char sector, unsigned char count,
                    GroupOfMeasurements *pDeltaGroup,
                    int printDeltas)
{
    char cmd[10];
    unsigned char insts[40];
    unsigned int mNo, timerValue, lastTvalue;
#if _MINMAX_VALUES_PRINTOUT
    unsigned int dMin=~0, dMax=0;
#endif
    struct Timer24bitValues T24Sample;

    SETSTATEDEBUG((void)0);

#if _ASCII_PARAMETER_PASSING
    // must be: "Ux <track> <sector>"
    // sprintf(cmd, "U%c %d %d", ExecuteJobInBuffer, i, i & 0x0f);
    sprintf(cmd, "U%c %d %d", ExecuteJobInBuffer, diskTrack, sector);
#else
    // must be: "Ux<track><sector>" with directly encoded bytes
    sprintf(cmd, "U%c%c%c", ExecuteJobInBuffer, diskTrack, sector);
#endif

    pDeltaGroup->trueNumberOfIntervals = 0;

    // for each track do 1 initialisation and then
    // several measurements
    timerValue = 0;
    for(mNo = 0; mNo <= count; mNo++)
    {
        lastTvalue = timerValue;

#if _ASCII_PARAMETER_PASSING
        if( cbm_exec_command(HandleDevice, DeviceAddress, cmd, strlen(cmd))
            != 0) return 1;
#else
        if( cbm_exec_command(HandleDevice, DeviceAddress, cmd, 4)
            != 0) return 1;
#endif
        SETSTATEDEBUG((void)0);

        // wait for job to finish
        if( cbm_device_status(HandleDevice, DeviceAddress, insts, sizeof(insts)) )
        {
            printf("%s\n", insts);
        }

        if( cbm_download(HandleDevice, DeviceAddress,
                     timerShotMain, (unsigned char *) & T24Sample,
                     sizeof(T24Sample))
             != sizeof(T24Sample)) return 1;

        // read out sample that was shot by the jobcode
        timerValue = reconstruct_v32bitInc(T24Sample);

        if(mNo > 0){
            lastTvalue = timerValue - lastTvalue;

            // increase by the number of overflows
            pDeltaGroup->trueNumberOfIntervals +=
                (lastTvalue + 100000) / 200000;

            if( printDeltas ) printf("%6u ", lastTvalue);
#if _MINMAX_VALUES_PRINTOUT
            if(lastTvalue > dMax) dMax = lastTvalue;
            if(lastTvalue < dMin) dMin = lastTvalue;
#endif
        }
        else
        {
            pDeltaGroup->startValue = timerValue;
            if( printDeltas ) printf(" %10u ||", timerValue);
        }
    }
#if _MINMAX_VALUES_PRINTOUT
    if( printDeltas ) printf(" %6u..%6u=%2u", dMin, dMax, dMax - dMin);
#endif

    pDeltaGroup->endValue = timerValue;
    return 0;
}