Example #1
0
static int open_disk(CBM_FILE fd, imgcopy_settings *settings,
                     const void *arg, int for_writing,
                     turbo_start start, imgcopy_message_cb message_cb)
{
    char buf[48];
    int rv;

    if(settings->end_track > settings->max_tracks)
    {
        message_cb(0, 
                   "standard transfer doesn't handle extended track images");
        return 99;
    }

    drive = (unsigned char)(ULONG_PTR)arg;

    fd_cbm = fd;

    cbm_open(fd_cbm, drive, 2, "#", 1);

    rv = cbm_device_status(fd_cbm, drive, buf, sizeof(buf));
    if(rv)
    {
        message_cb(0, "drive %02d: %s", drive, buf);
    }
    return rv;
}
Example #2
0
static int read_block(unsigned char tr, unsigned char se, unsigned char *block)
{
    char cmd[48];
    int rv = 1;

    sprintf(cmd, "U1:2 0 %d %d", tr, se);
    if(cbm_exec_command(fd_cbm, drive, cmd, 0) == 0) {
        rv = cbm_device_status(fd_cbm, drive, cmd, sizeof(cmd));
        if(rv == 0) {
            if(cbm_exec_command(fd_cbm, drive, "B-P2 0", 0) == 0) {
                if(cbm_talk(fd_cbm, drive, 2) == 0) {
                                                                        SETSTATEDEBUG(debugLibImgByteCount=0);
                    rv = cbm_raw_read(fd_cbm, block, BLOCKSIZE) != BLOCKSIZE;
                                                                        SETSTATEDEBUG(debugLibImgByteCount=-1);
                    cbm_untalk(fd_cbm);
                }
            }
        }
    }
    return rv;
}
Example #3
0
static int write_block(unsigned char tr, unsigned char se, const unsigned char *blk, int size, int read_status)
{
    char cmd[48];
    int  rv = 1;

    if(cbm_exec_command(fd_cbm, drive, "B-P2 0", 0) == 0)
    {
        if(cbm_listen(fd_cbm, drive, 2) == 0)
        {
                                                                        SETSTATEDEBUG(debugLibImgByteCount=0);
            rv = cbm_raw_write(fd_cbm, blk, size) != size;
                                                                        SETSTATEDEBUG(debugLibImgByteCount=-1);
            cbm_unlisten(fd_cbm);
            if(rv == 0)
            {
                sprintf(cmd ,"U2:2 0 %d %d", tr, se);
                cbm_exec_command(fd_cbm, drive, cmd, 0);
                rv = cbm_device_status(fd_cbm, drive, cmd, sizeof(cmd));
            }
        }
    }
    return rv;
}
Example #4
0
File: main.c Project: bogde/OpenCBM
int ARCH_MAINDECL main(int argc, char **argv)
{
    CBM_FILE fd;
    FILE *file;
    char *fname;

    int mode;
    int c;
    unsigned char *filedata;
    size_t filesize;
    char buf[48];
    int num_entries;
    int num_files;
    int rv;
    int i;
    int write;
    cbmcopy_settings *settings;
    char auto_name[17];
    char auto_type = '\0';
    char output_type = '\0';
    char *tail;
    char *ext;
    char *adapter = NULL;

    unsigned char drive;
    const char *tm = NULL;
    const char *dt = NULL;
    int force_raw = 0;
    int address = -1;
    const char *output_name = NULL;
    const char *address_str = NULL;
    char *fs_name;

    input_reader *readers[] =
    {
        &cbmwrite_raw,   /* must be first, as it is default */
        &cbmwrite_pc64,
        &cbmwrite_t64,
        NULL
    };

    input_reader *rd;

    struct option longopts[] =
    {
        { "help"            , no_argument      , NULL, 'h' },
        { "verbose"         , no_argument      , NULL, 'v' },
        { "adapter"         , required_argument, NULL, '@' },
        { "quiet"           , no_argument      , NULL, 'q' },
        { "version"         , no_argument      , NULL, 'V' },
        { "no-progress"     , no_argument      , NULL, 'n' },
        { "read"            , no_argument      , NULL, 'r' },
        { "write"           , no_argument      , NULL, 'w' },
        { "transfer"        , required_argument, NULL, 't' },
        { "drive-type"      , required_argument, NULL, 'd' },
        { "file-type"       , required_argument, NULL, 'f' },
        { "output"          , required_argument, NULL, 'o' },
        { "raw"             , no_argument      , NULL, 'R' },
        { "address"         , no_argument      , NULL, 'a' },
        { NULL              , 0                , NULL, 0   }
    };

    const char shortopts[] ="hVqvrwnt:d:f:o:Ra:@:";

    if(NULL == (tail = strrchr(argv[0], '/')))
    {
        tail = argv[0];
    }
    else
    {
        tail++;
    }
    if(strcmp(tail, "cbmread") == 0)
    {
        mode = 'r'; /* read */
    }
    else if(strcmp(tail, "cbmwrite") == 0)
    {
        mode = 'w'; /* write */
    }
    else
    {
        mode = EOF; /* mode must be given later */
    }

    settings = cbmcopy_get_default_settings();

    /* loop over cmd line opts */
    while((c=getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
    {
        switch(c)
        {
            case 'h': /* --help */
                help(argv[0]);
                return 0;
            case 'V': /* --version */
                printf("cbmcopy %s\n", OPENCBM_VERSION);
                return 0;
            case 'q': /* -- quiet */
                if(verbosity > sev_fatal)
                    verbosity--;
                break;
            case 'v': /* --verbose */
                if(verbosity < sev_debug)
                    verbosity++;
                break;
            case 'n': /* --no-progress */
                no_progress = 1;
                break;

            case 'r': /* --read */
            case 'w': /* --write */
                if(mode != EOF)
                {
                    my_message_cb(sev_fatal, "-r/-w given more than once");
                    hint(argv[0]);
                    return 1;
                }
                mode = c;
                break;

            case 't': /* --transfer */
                char_star_opt_once(&tm, "--transfer", argv);
                break;
            case 'd': /* --drive-type */
                char_star_opt_once(&dt, "--drive-type", argv);
                break;
            case 'o': /* --output */
                char_star_opt_once(&output_name, "--output", argv);
                break;
            case 'f': /* --file-type */
                output_type = (char) toupper(*optarg);
                break;
            case 'R': /* --raw */
                force_raw = 1;
                break;
            case 'a': /* override-address */
                char_star_opt_once(&address_str, "--address", argv);
                break;
            case '@': /* choose adapter */
                if (adapter == NULL)
                    adapter = cbmlibmisc_strdup(optarg);
                else {
                    my_message_cb(sev_fatal, "--adapter/-@ given more than once.");
                    hint(argv[0]);
                    exit(1);
                }
                break;
            default : /* unknown */
                hint(argv[0]);
                return 1;
        }
    }

    /* check -r/-w */
    switch(mode)
    {
        case 'r' :
            write = 0;
            break;
        case 'w' :
            write = 1;
            break;
        default:
            my_message_cb(sev_fatal,
                          "-r or -w must be given when started as `%s'",
                          argv[0]);
            hint(argv[0]);
            return 1;
    }

    /* check transfer mode */
    settings->transfer_mode = cbmcopy_get_transfer_mode_index(tm);
    if(settings->transfer_mode < 0)
    {
        my_message_cb(sev_fatal, "Unknown transfer mode: %s", tm);
        return 1;
    }

    /* check device type */
    if(dt)
    {
        const struct
        {
            const char *str;
            enum cbm_device_type_e type;
        }
        *p, types[] =
        {
            { "1541", cbm_dt_cbm1541 }, { "1571", cbm_dt_cbm1571 },
            { "1570", cbm_dt_cbm1570 }, { "1581", cbm_dt_cbm1581 },
            { NULL  , cbm_dt_unknown }
        };

        for(p = types; p->str && strcmp(dt, p->str); p++)
            ; /* nothing */

        if(!p->str)
        {
            my_message_cb(sev_fatal, "Unknown drive type: %s", dt);
            return 1;
        }
        settings->drive_type = p->type;
    }

    /* check CBM file type */
    if(output_type)
    {
        if(write)
        {
            if(strchr("DSPU", output_type) == NULL)
            {
                my_message_cb(sev_fatal, "Invalid file type : %c", output_type);
            }
        }
        else
        {
            my_message_cb(sev_warning, "--file-type ignored");
        }
    }

    /* check load address override */
    if(address_str)
    {
        address = strtol(address_str, &tail, 0);
        if(*tail || address < 0 || address > 0xffff)
        {
            my_message_cb(sev_fatal, "--address invalid: %s", address_str);
            hint(argv[0]);
            return 1;
        }
    }

    /* first non-option is device number */
    if(optind == argc)
    {
        my_message_cb(sev_fatal, "%s: No drive number given", argv[0]);
        hint(argv[0]);
        return 1;
    }

    drive = (unsigned char) strtol(argv[optind], &tail, 0);
    if(drive < 8 || drive > 11 || *tail)
    {
        my_message_cb(sev_fatal, "invalid drive: `%s'", argv[optind]);
        return 1;
    }

    /* remaining args are file names */
    num_files = argc - optind - 1;

    if(num_files == 0)
    {
        my_message_cb(sev_fatal, "%s: No files?", argv[0]);
        hint(argv[0]);
        return 1;
    }

    /* more than one file name given, avoid -o option */
    if(num_files > 1 && output_name)
    {
        my_message_cb(sev_fatal, "--output requires exactly one file name");
        return 1;
    }

    rv = cbm_driver_open_ex( &fd, adapter );
    cbmlibmisc_strfree(adapter);

    if(0 == rv)
    {
        fd_cbm = fd;

        /*
         * If the user specified auto transfer mode, find out
         * which transfer mode to use.
         */
        settings->transfer_mode = 
            cbmcopy_check_auto_transfer_mode(fd_cbm,
                settings->transfer_mode,
                drive);

        arch_set_ctrlbreak_handler(reset);

        while(++optind < argc)
        {
            fname = argv[optind];
            if(write)
            {
                rd = readers[0];

                file = fopen(fname, "rb");
                if(file)
                {
                    num_entries = 0;
                    if(!force_raw)
                    {
                        /* try to detect file format */
                        for(i = 1; readers[i] && !num_entries; i++)
                        {
                            num_entries =
                                readers[i]->probe( file, fname, my_message_cb );
                            if(num_entries)
                                rd = readers[i];
                        }
                    }
                    if(!num_entries) num_entries = 1; /* raw file */

                    for(i = 0; i < num_entries; i++)
                    {
                        my_message_cb( sev_debug,
                                       "processing entry %d from %s",
                                       i, fname );
                        if(rd->read(file, fname, i,
                                    auto_name, &auto_type,
                                    &filedata, &filesize, my_message_cb ) == 0)
                        {
                            buf[16] = '\0';
                            if(output_name)
                            {
                                strncpy(buf, output_name, 16);
                                cbm_ascii2petscii(buf);
                            }
                            else
                            {
                                /* no charset conversion */
                                strncpy(buf, auto_name, 16);
                            }
                            strcat(buf, ",x");
                            buf[strlen(buf)-1] =
                                output_type ? output_type : auto_type;
                            strcat(buf, ",W");

                            my_message_cb( sev_info,
                                           "writing %s -> %s", fname, buf );

                            if(address >= 0 && filesize > 1)
                            {
                                filedata[0] = address % 0x100;
                                filedata[1] = address / 0x100;

                                my_message_cb( sev_debug, 
                                               "override address: $%02x%02x",
                                               filedata[1], filedata[0] );

                            }
                            if(cbmcopy_write_file(fd, settings, drive,
                                                  buf, strlen(buf),
                                                  filedata, filesize,
                                                  my_message_cb,
                                                  my_status_cb) == 0)
                            {
                                printf("\n");
                                rv = cbm_device_status( fd, drive,
                                                        buf, sizeof(buf) );
                                my_message_cb( rv ?  sev_warning : sev_info,
                                               "%s", buf );
                            }
                            else
                                printf("\n");

                            if(filedata)
                            {
                                free(filedata);
                            }
                        }
                        else
                        {
                            my_message_cb( sev_warning,
                                           "error processing entry %d from %s",
                                           i, fname );
                        }
                    }
                }
                else
                {
                    my_message_cb( sev_warning,
                                   "warning could not read %s: %s",
                                   fname, arch_strerror(arch_get_errno()) );
                }
            }
            else
            {
                strncpy(buf, fname, 16);
                buf[16] = '\0';
                cbm_ascii2petscii(buf);

                if(output_name)
                {
                    fs_name = arch_strdup(output_name);
                }
                else
                {
                    for(tail = fname; *tail && *tail != ','; tail++);

                    ext = "prg"; /* default */

                    if(*tail)
                    {
                        tail++;
                        switch(*tail)
                        {
                            case 'D': ext = "del"; break;
                            case 'S': ext = "seq"; break;
                            case 'U': ext = "usr"; break;
                        }
                    }
                    fs_name = malloc(strlen(fname) + strlen(ext) + 2);
                    if(fs_name) sprintf(fs_name, "%s.%s", fname, ext);
                }

                if(fs_name)
                {
                    for(tail = fs_name; *tail; tail++)
                    {
                        if(*tail == '/') *tail = '_';
                    }
                }
                else
                {
                    /* should not happen... */
                    cbm_driver_close( fd );
                    my_message_cb(sev_fatal, "Out of memory");
                    exit(1);
                }

                my_message_cb( sev_info, "reading %s -> %s", buf, fs_name );

                if(cbmcopy_read_file(fd, settings, drive, buf, strlen(buf),
                                     &filedata, &filesize,
                                     my_message_cb, my_status_cb) == 0)
                {
                    rv = cbm_device_status( fd, drive, buf, sizeof(buf) );
                    my_message_cb( rv ? sev_warning : sev_info, "%s", buf );

                    file = fopen(fs_name, "wb");
                    if(file)
                    {
                        if(filedata)
                        {
                            if(address >= 0 && filesize > 1)
                            {
                                filedata[0] = address % 0x100;
                                filedata[1] = address / 0x100;

                                my_message_cb( sev_debug, 
                                               "override address: $%02x%02x",
                                               filedata[1], filedata[0] );
                            }
                            if(fwrite(filedata, filesize, 1, file) != 1)
                            {
                                my_message_cb(sev_warning,
                                              "could not write %s: %s",
                                              fs_name, arch_strerror(arch_get_errno()));
                            }
                        }
                        fclose(file);
                    }
                    else
                    {
                        my_message_cb(sev_warning,
                                      "could not open %s: %s",
                                      fs_name, arch_strerror(arch_get_errno()));
                    }

                    if(filedata)
                    {
                        free(filedata);
                    }
                }
                else
                {
                    my_message_cb(sev_warning, "error reading %s", buf);
                }
                if(fs_name)
                {
                    free(fs_name);
                }
            }
        }
        cbm_driver_close( fd );

        if(rv)
        {
            my_message_cb(sev_warning, "there was at least one error" );
        }
    }

    return rv;
}
Example #5
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;
}
Example #6
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
            {
Example #7
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;
}
Example #8
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
            {
Example #9
0
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
    {
Example #10
0
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;
}