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; }
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; }
// // 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); }
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]§ors) 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]§ors) + trackTailGAP - data[i+1]) RPMval = (flags != 0x01) ? RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]§ors) + 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 {
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; }
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]§ors) 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]§ors) + trackTailGAP - data[i+1]) RPMval = (flags != 0x01) ? RPMval / (sectors * (10+20+18+10 + 650 + data[i+1]) - (0x01&data[i+1]§ors) + 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 {
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 {
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; }