Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

cbmcopy.c

00001 /*
00002  *  This program is free software; you can redistribute it and/or
00003  *  modify it under the terms of the GNU General Public License
00004  *  as published by the Free Software Foundation; either version
00005  *  2 of the License, or (at your option) any later version.
00006  *
00007  *  Copyright 2001 Michael Klein <michael(dot)klein(at)puffin(dot)lb(dot)shuttle(dot)de>
00008  */
00009 
00010 #ifdef SAVE_RCSID
00011 static char *rcsid =
00012     "@(#) $Id: cbmcopy.c,v 1.18 2006/04/18 08:04:48 trikalio Exp $";
00013 #endif
00014 
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <assert.h>
00019 #include "opencbm.h"
00020 #include "cbmcopy.h"
00021 
00022 #include "cbmcopy_int.h"
00023 
00024 #include "arch.h"
00025 
00026 static const unsigned char turboread1541[] = {
00027 #include "turboread1541.inc"
00028 };
00029 
00030 static const unsigned char turboread1571[] = {
00031 #include "turboread1571.inc"
00032 };
00033 
00034 static const unsigned char turboread1581[] = {
00035 #include "turboread1581.inc"
00036 };
00037 
00038 static const unsigned char turbowrite1541[] = {
00039 #include "turbowrite1541.inc"
00040 };
00041 
00042 static const unsigned char turbowrite1571[] = {
00043 #include "turbowrite1571.inc"
00044 };
00045 
00046 static const unsigned char turbowrite1581[] = {
00047 #include "turbowrite1581.inc"
00048 };
00049 
00050 extern transfer_funcs cbmcopy_s1_transfer,
00051                       cbmcopy_s2_transfer,
00052                       cbmcopy_pp_transfer;
00053 
00054 static struct _transfers
00055 {
00056     const transfer_funcs *trf;
00057     const char *name, *abbrev;
00058 }
00059 transfers[] =
00060 {
00061     { &cbmcopy_s1_transfer, "auto", "a%1" },
00062     { &cbmcopy_s1_transfer, "serial1", "s1" },
00063     { &cbmcopy_s2_transfer, "serial2", "s2" },
00064     { &cbmcopy_pp_transfer, "parallel", "p%" },
00065     { NULL, NULL, NULL }
00066 };
00067 
00068 #ifdef CBMCOPY_DEBUG
00069 signed int debugLineNumber=0, debugBlockCount=0, debugByteCount=0;
00070 
00071 #   define SETSTATEDEBUG(_x)  \
00072     debugLineNumber=__LINE__; \
00073     (_x)
00074 
00075 void printDebugCounters(cbmcopy_message_cb msg_cb)
00076 {
00077     msg_cb( sev_info, "file: " __FILE__
00078                       "\n\tversion: " OPENCBM_VERSION ", built: " __DATE__ " " __TIME__
00079                       "\n\tlineNumber=%d, blockCount=%d, byteCount=%d\n",
00080                       debugLineNumber, debugBlockCount, debugByteCount);
00081 }
00082 #else
00083 #    define SETSTATEDEBUG(_x) (void)0
00084 #endif
00085 
00086 static int check_drive_type(CBM_FILE fd, unsigned char drive,
00087                             cbmcopy_settings *settings,
00088                             cbmcopy_message_cb msg_cb)
00089 {
00090     const char *type_str;
00091 
00092     if( settings->drive_type == cbm_dt_unknown )
00093     {
00094         if(cbm_identify( fd, drive, &settings->drive_type, &type_str ))
00095         {
00096             msg_cb( sev_warning, "could not identify drive, using 1541 turbo" );
00097             settings->drive_type = cbm_dt_cbm1541;
00098         }
00099         else
00100         {
00101             msg_cb( sev_info, "identified a %s drive", type_str );
00102         }
00103     }
00104     return 0;
00105 }
00106 
00107 
00108 static int send_turbo(CBM_FILE fd, unsigned char drive, int write,
00109                       const cbmcopy_settings *settings,
00110                       const unsigned char *turbo, size_t turbo_size,
00111                       const unsigned char *start_cmd, size_t cmd_len,
00112                       cbmcopy_message_cb msg_cb)
00113 {
00114     const transfer_funcs *trf;
00115 
00116     trf = transfers[settings->transfer_mode].trf;
00117     cbm_upload( fd, drive, 0x500, turbo, turbo_size );
00118     msg_cb( sev_debug, "uploading %d bytes turbo code", turbo_size );
00119     if(trf->upload_turbo(fd, drive, settings->drive_type, write) == 0)
00120     {
00121         cbm_exec_command( fd, drive, start_cmd, cmd_len );
00122         msg_cb( sev_debug, "initializing transfer code" );
00123         if(trf->start_turbo(fd, write) == 0)
00124         {
00125             msg_cb( sev_debug, "done" );
00126             return 0;
00127         }
00128         else
00129         {
00130             msg_cb( sev_fatal, "could not start turbo" );
00131         }
00132     }
00133     else
00134     {
00135         msg_cb( sev_fatal, "Unsupported transfer mode for this device" );
00136     }
00137     return -1;
00138 }
00139 
00140 
00141 static int cbmcopy_read(CBM_FILE fd,
00142                         cbmcopy_settings *settings,
00143                         unsigned char drive,
00144                         int track, int sector,
00145                         const char *cbmname,
00146                         int cbmname_len,
00147                         unsigned char **filedata,
00148                         size_t *filedata_size,
00149                         cbmcopy_message_cb msg_cb,
00150                         cbmcopy_status_cb status_cb)
00151 {
00152     int rv;
00153     int i;
00154     int turbo_size;
00155     int error;
00156     unsigned char c;
00157     unsigned char *cptr;
00158     unsigned char buf[48];
00159     const unsigned char *turbo;
00160     const transfer_funcs *trf;
00161     int blocks_read;
00162 
00163     *filedata = NULL;
00164     *filedata_size = 0;
00165 
00166     msg_cb( sev_debug, "using transfer mode `%sī",
00167             transfers[settings->transfer_mode].name);
00168     trf = transfers[settings->transfer_mode].trf;
00169 
00170     if(check_drive_type( fd, drive, settings, msg_cb ))
00171     {
00172         return -1;
00173     }
00174 
00175     switch(settings->drive_type)
00176     {
00177         case cbm_dt_cbm1541:
00178             turbo = turboread1541;
00179             turbo_size = sizeof(turboread1541);
00180             break;
00181         case cbm_dt_cbm1570:
00182         case cbm_dt_cbm1571:
00183             cbm_exec_command( fd, drive, "U0>M1", 0 );
00184             turbo = turboread1571;
00185             turbo_size = sizeof(turboread1571);
00186             break;
00187         case cbm_dt_cbm1581:
00188             turbo = turboread1581;
00189             turbo_size = sizeof(turboread1581);
00190             break;
00191         default: /* unreachable */
00192             return -1;
00193     }
00194 
00195     if(cbmname)
00196     {
00197         /* start by file name */
00198         track = 0;
00199         sector = 0;
00200         cbm_open( fd, drive, 0, NULL, 0 );
00201         if(cbmname_len == 0) cbmname_len = strlen( cbmname );
00202         cbm_raw_write( fd, cbmname, cbmname_len );
00203         cbm_unlisten( fd );
00204     }
00205     else
00206     {
00207         /* start by track/sector */
00208         cbm_open( fd, drive, 0, "#", 1 );
00209     }
00210     rv = cbm_device_status( fd, drive, (char*)buf, sizeof(buf) );
00211 
00212     if(rv)
00213     {
00214         msg_cb( sev_fatal, "could not open file for reading: %s", buf );
00215         cbm_driver_close(fd);
00216         return rv;
00217     }
00218 
00219     blocks_read = 0;
00220     error = 0;
00221 
00222     if(track)
00223     {
00224         msg_cb( sev_debug, "start read at %d/%d", track, sector );
00225     }
00226     sprintf( (char*)buf, "U4:%c%c", (unsigned char)track, (unsigned char)sector );
00227 
00228     SETSTATEDEBUG((void)0);    // pre send_turbo condition
00229     if(send_turbo(fd, drive, 0, settings,
00230                   turbo, turbo_size, buf, 5, msg_cb) == 0)
00231     {
00232         msg_cb( sev_debug, "start of copy" );
00233         status_cb( blocks_read );
00234 
00235         /*
00236          * FIXME: Find and eliminate the real protocol races to
00237          *        eliminate the rare hangups with the 1581 based
00238          *        turbo routines (bugs suspected in 6502 code)
00239          *
00240          * Hotfix proposion for the 1581 protocols:
00241          *    add a little delay after the turbo start
00242          */
00243         arch_usleep(1000);
00244 
00245         SETSTATEDEBUG(debugBlockCount=0);   // turbo sent condition
00246 
00247         for(c = 0xff;
00248             c == 0xff && (error = trf->check_error(fd, 0)) == 0;
00249             /* nothing */ )
00250         {
00251             SETSTATEDEBUG((void)0);    // after check_error condition
00252 
00253             c = trf->read_byte( fd );
00254 
00255             SETSTATEDEBUG((void)0);    // afterwait condition
00256 
00257             i = (c == 0xff) ? 0xfe : c;
00258             *filedata_size += i;
00259 
00260             SETSTATEDEBUG(debugBlockCount++);    // preset condition
00261 
00262             /* @SRT: FIXME! the next statement is dangerous: If there 
00263              * is no memory block large enough for reallocating, the
00264              * memory block is not freed, but realloc() returns NULL,
00265              * thus, we have a memory leak.
00266              */
00267             *filedata = realloc(*filedata, *filedata_size);
00268 
00269             SETSTATEDEBUG((void)0);    // after check_error condition
00270             if(*filedata)
00271             {
00272                 SETSTATEDEBUG(debugByteCount=0);
00273 #ifdef CBMCOPY_DEBUG
00274                 msg_cb( sev_debug, "receive block data (%d)", c );
00275 #endif 
00276                 for(cptr = (*filedata) + blocks_read * 254; i; i--)
00277                 {
00278                     SETSTATEDEBUG(debugByteCount++);
00279                     *(cptr++) = trf->read_byte( fd );
00280                 }
00281                 /* (drive is busy now) */
00282                 SETSTATEDEBUG((void)0);    // after blockloop condition
00283 
00284                 /*
00285                  * FIXME: Find and eliminate the real protocol races to
00286                  *        eliminate the rare hangups with the 1581 based
00287                  *        turbo routines (bugs suspected in 6502 code)
00288                  *
00289                  * Hotfix proposion for the 1581 protocols:
00290                  *    add a little delay at the end of the loop
00291                  *       "hmmmm, if we know that the drive is busy
00292                  *        now, shouldn't we wait for it then?"
00293                  *    add a little delay after the turbo start
00294                  */
00295                 arch_usleep(1000);
00296 
00297                 SETSTATEDEBUG((void)0);    // afterread condition
00298                 status_cb( ++blocks_read );
00299             }
00300             else
00301             {
00302                 /* FIXME */
00303             }
00304 
00305             SETSTATEDEBUG((void)0);    // pre loop condition
00306         }
00307         msg_cb( sev_debug, "done" );
00308         SETSTATEDEBUG((void)0);    // end loop condition
00309         trf->exit_turbo( fd, 0 );
00310         SETSTATEDEBUG((void)0);    // turbo exited condition
00311 
00312         /*
00313          * FIXME: Find and eliminate the real protocol race to
00314          *        eliminate a rare "99, DRIVER ERROR,00,00" with the
00315          *        1571 disk drive and the serial-2 read turbo
00316          *
00317          * Hotfix proposion for the 1571 protocol:
00318          *    add a listen/unlisten sequence, just doing a decent
00319          *    arch_usleep() and waiting some time did not work
00320          */
00321         cbm_listen(fd, drive, 0);
00322         cbm_unlisten(fd);
00323         SETSTATEDEBUG((void)0);    // turbo exited, waited for drive
00324     }
00325 
00326     return rv;
00327 }
00328 
00329 
00330 char *cbmcopy_get_transfer_modes()
00331 {
00332     const struct _transfers *t;
00333     int size;
00334     char *buf;
00335     char *dst;
00336 
00337     size = 1; /* for terminating '\0' */
00338     for(t = transfers; t->name; t++)
00339     {
00340         size += (strlen(t->name) + 1);
00341     }
00342 
00343     buf = malloc(size);
00344 
00345     if(buf)
00346     {
00347         dst = buf;
00348         for(t = transfers; t->name; t++)
00349         {
00350             strcpy(dst, t->name);
00351             dst += (strlen(t->name) + 1);
00352         }
00353         *dst = '\0';
00354     }
00355 
00356     return buf;
00357 }
00358 
00359 
00360 int cbmcopy_get_transfer_mode_index(const char *name)
00361 {
00362     const struct _transfers *t;
00363     int i;
00364     int abbrev_len;
00365     int tm_len;
00366 
00367     if(NULL == name)
00368     {
00369         /* default transfer mode */
00370         return 0;
00371     }
00372 
00373     tm_len = strlen(name);
00374     for(i = 0, t = transfers; t->name; i++, t++)
00375     {
00376         if(strcmp(name, t->name) == 0)
00377         {
00378             /* full match */
00379             return i;
00380         }
00381         if(t->abbrev[strlen(t->abbrev)-1] == '%')
00382         {
00383             abbrev_len = strlen(t->abbrev) - 1;
00384             if(abbrev_len <= tm_len && strncmp(t->name, name, tm_len) == 0)
00385             {
00386                 return i;
00387             }
00388         }
00389         else
00390         {
00391             if(strcmp(name, t->abbrev) == 0)
00392             {
00393                 return i;
00394             }
00395         }
00396     }
00397     return -1;
00398 }
00399 
00400 int cbmcopy_check_auto_transfer_mode(CBM_FILE cbm_fd, int auto_transfermode, int drive)
00401 {
00402     int transfermode = auto_transfermode;
00403 
00404     /* We assume auto is the first transfer mode */
00405     assert(strcmp(transfers[0].name, "auto") == 0);
00406 
00407     if (auto_transfermode == 0)
00408     {
00409         do {
00410             enum cbm_cable_type_e cable_type;
00411             unsigned char testdrive;
00412 
00413             /*
00414              * Test the cable
00415              */
00416 
00417             if (cbm_identify_xp1541(cbm_fd, (unsigned char)drive, NULL, &cable_type) == 0)
00418             {
00419                 if (cable_type == cbm_ct_xp1541)
00420                 {
00421                     /*
00422                      * We have a parallel cable, use that
00423                      */
00424                     transfermode = cbmcopy_get_transfer_mode_index("parallel");
00425                     break;
00426                 }
00427             }
00428 
00429             /*
00430              * We do not have a parallel cable. Check if we are the only drive
00431              * on the bus, so we can use serial2, at least.
00432              */
00433 
00434             for (testdrive = 4; testdrive < 31; ++testdrive)
00435             {
00436                 enum cbm_device_type_e device_type;
00437 
00438                 /* of course, the drive to be transfered to is present! */
00439                 if (testdrive == drive)
00440                     continue;
00441 
00442                 if (cbm_identify(cbm_fd, testdrive, &device_type, NULL) == 0)
00443                 {
00444                     /*
00445                      * My bad, there is another drive -> only use serial1
00446                      */
00447                     transfermode = cbmcopy_get_transfer_mode_index("serial1");
00448                     break;
00449                 }
00450             }
00451 
00452             /*
00453              * If we reached here with transfermode 0, we are the only
00454              * drive, thus, use serial2.
00455              */
00456             if (transfermode == 0)
00457                 transfermode = cbmcopy_get_transfer_mode_index("serial2");
00458 
00459         } while (0);
00460     }
00461 
00462     return transfermode;
00463 }
00464 
00465 cbmcopy_settings *cbmcopy_get_default_settings(void)
00466 {
00467     cbmcopy_settings *settings;
00468 
00469     settings = malloc(sizeof(cbmcopy_settings));
00470 
00471     if(NULL != settings)
00472     {
00473         settings->drive_type    = cbm_dt_unknown; /* auto detect later on */
00474         settings->transfer_mode = 0;
00475     }
00476     return settings;
00477 }
00478 
00479 
00480 
00481 int cbmcopy_write_file(CBM_FILE fd,
00482                        cbmcopy_settings *settings,
00483                        int drivei,
00484                        const char *cbmname,
00485                        int cbmname_len,
00486                        const unsigned char *filedata,
00487                        int filedata_size,
00488                        cbmcopy_message_cb msg_cb,
00489                        cbmcopy_status_cb status_cb)
00490 {
00491     int rv;
00492     int i;
00493     int turbo_size;
00494     unsigned char drive = (unsigned char) drivei; 
00495     int error;
00496     unsigned char c;
00497     unsigned char buf[48];
00498     const unsigned char *turbo;
00499     const transfer_funcs *trf;
00500     int blocks_written;
00501 
00502     msg_cb( sev_debug, "using transfer mode `%sī",
00503             transfers[settings->transfer_mode].name);
00504     trf = transfers[settings->transfer_mode].trf;
00505 
00506     if(check_drive_type( fd, drive, settings, msg_cb ))
00507     {
00508         return -1;
00509     }
00510 
00511     switch(settings->drive_type)
00512     {
00513         case cbm_dt_cbm1541:
00514             turbo = turbowrite1541;
00515             turbo_size = sizeof(turbowrite1541);
00516             break;
00517         case cbm_dt_cbm1570:
00518         case cbm_dt_cbm1571:
00519             cbm_exec_command( fd, drive, "U0>M1", 0 );
00520             turbo = turbowrite1571;
00521             turbo_size = sizeof(turbowrite1571);
00522             break;
00523         case cbm_dt_cbm1581:
00524             turbo = turbowrite1581;
00525             turbo_size = sizeof(turbowrite1581);
00526             break;
00527         default: /* unreachable */
00528             return -1;
00529     }
00530 
00531     cbm_open( fd, drive, 1, NULL, 0 );
00532     if(cbmname_len == 0) cbmname_len = strlen( cbmname );
00533     cbm_raw_write( fd, cbmname, cbmname_len );
00534     cbm_unlisten( fd );
00535     rv = cbm_device_status( fd, drive, buf, sizeof(buf) );
00536 
00537     if(rv)
00538     {
00539         msg_cb( sev_fatal, "could not open file for writing: %s", buf );
00540         cbm_driver_close(fd);
00541         return rv;
00542     }
00543 
00544     blocks_written = 0;
00545     error = 0;
00546 
00547     SETSTATEDEBUG((void)0);    // pre send_turbo condition
00548     if(send_turbo(fd, drive, 1, settings,
00549                   turbo, turbo_size, (unsigned char*)"U4:", 3, msg_cb) == 0)
00550     {
00551         msg_cb( sev_debug, "start of copy" );
00552         status_cb( blocks_written );
00553 
00554         /*
00555          * FIXME: Find and eliminate the real protocol races to
00556          *        eliminate the rare hangups with the 1581 based
00557          *        turbo routines (bugs suspected in 6502 code)
00558          *
00559          * Hotfix proposion for the 1581 protocols:
00560          *    add a little delay after the turbo start
00561          */
00562         arch_usleep(1000);
00563 
00564         SETSTATEDEBUG(debugBlockCount=0);
00565 
00566         for(i = 0;
00567             (i == 0) || (i < filedata_size && !error );
00568             i+=254)
00569         {
00570             if( filedata_size - i <= 254 )
00571             {
00572                 c = filedata_size - i;
00573             }
00574             else
00575             {
00576                 c = 255;
00577             }
00578             SETSTATEDEBUG(debugBlockCount++);
00579 #ifdef CBMCOPY_DEBUG
00580             msg_cb( sev_debug, "send byte count: %d", c );
00581 #endif
00582             trf->write_byte( fd, c );
00583             SETSTATEDEBUG((void)0);
00584 
00585             if(c)
00586             {
00587                 SETSTATEDEBUG(debugByteCount=0);
00588 #ifdef CBMCOPY_DEBUG
00589                 msg_cb( sev_debug, "send block data" );
00590 #endif 
00591                 if( c == 0xff ) c = 0xfe;
00592                 while(c)
00593                 {
00594                     SETSTATEDEBUG(debugByteCount++);
00595                     trf->write_byte( fd, *(filedata++) );
00596                     c--;
00597                 }
00598 
00599                 /* (drive is busy now) */
00600                 
00601                 SETSTATEDEBUG((void)0);
00602             }
00603             error = trf->check_error( fd, 1 );
00604             SETSTATEDEBUG((void)0);
00605 
00606             /*
00607              * FIXME: Find and eliminate the real protocol races to
00608              *        eliminate the rare hangups with the 1581 based
00609              *        turbo routines (bugs suspected in 6502 code)
00610              *
00611              * Hotfix proposion for the 1581 protocols:
00612              *    add a little delay at the end of the loop
00613              *       "hmmmm, if we know that the drive is busy
00614              *        now, shouldn't we wait for it then?"
00615              *    add a little delay after the turbo start
00616              */
00617             arch_usleep(1000);
00618 
00619             if(!error)
00620             {
00621                 status_cb( ++blocks_written );
00622             }
00623             SETSTATEDEBUG((void)0);
00624         }
00625         msg_cb( sev_debug, "done" );
00626 
00627         SETSTATEDEBUG((void)0);
00628         trf->exit_turbo( fd, 1 );
00629         SETSTATEDEBUG((void)0);
00630     }
00631     return rv;
00632 }
00633 
00634 
00635 /* just a wrapper */
00636 int cbmcopy_read_file_ts(CBM_FILE fd,
00637                          cbmcopy_settings *settings,
00638                          int drive,
00639                          int track, int sector,
00640                          unsigned char **filedata,
00641                          size_t *filedata_size,
00642                          cbmcopy_message_cb msg_cb,
00643                          cbmcopy_status_cb status_cb)
00644 {
00645     return cbmcopy_read(fd, settings, (unsigned char) drive,
00646                         track, sector,
00647                         NULL, 0,
00648                         filedata, filedata_size,
00649                         msg_cb, status_cb);
00650 }
00651 
00652 
00653 /* just a wrapper */
00654 int cbmcopy_read_file(CBM_FILE fd,
00655                       cbmcopy_settings *settings,
00656                       int drive,
00657                       const char *cbmname,
00658                       int cbmname_len,
00659                       unsigned char **filedata,
00660                       size_t *filedata_size,
00661                       cbmcopy_message_cb msg_cb,
00662                       cbmcopy_status_cb status_cb)
00663 {
00664     return cbmcopy_read(fd, settings, (unsigned char) drive,
00665                         0, 0,
00666                         cbmname, cbmname_len,
00667                         filedata, filedata_size,
00668                         msg_cb, status_cb);
00669 }

Generated on Sun Apr 30 18:45:43 2006 for opencbm by  doxygen 1.4.2