コード例 #1
0
ファイル: cbmforng.c プロジェクト: Flaviowebit/openCBM
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
            {
コード例 #2
0
ファイル: frm_analyzer.c プロジェクト: Flaviowebit/openCBM
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
            {
コード例 #3
0
ファイル: cbmrpm41.c プロジェクト: bogde/OpenCBM
static int
measure_2cyleJitter(CBM_FILE HandleDevice, unsigned char DeviceAddress,
                    unsigned char diskTrack, unsigned char sector, unsigned char count,
                    GroupOfMeasurements *pDeltaGroup,
                    int printDeltas)
{
    char cmd[10];
    unsigned char insts[40];
    unsigned int mNo, timerValue, lastTvalue;
#if _MINMAX_VALUES_PRINTOUT
    unsigned int dMin=~0, dMax=0;
#endif
    struct Timer24bitValues T24Sample;

    SETSTATEDEBUG((void)0);

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

    pDeltaGroup->trueNumberOfIntervals = 0;

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

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

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

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

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

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

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

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

    pDeltaGroup->endValue = timerValue;
    return 0;
}