00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifdef SAVE_RCSID
00013 static char *rcsid =
00014 "@(#) $Id: cbmctrl.c,v 1.48 2006/04/13 11:40:05 trikalio Exp $";
00015 #endif
00016
00017 #include "opencbm.h"
00018
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022
00023 typedef int (*mainfunc)(CBM_FILE fd, char *argv[]);
00024
00025 #include "arch.h"
00026
00027 static const unsigned char prog_tdchange[] = {
00028 #include "tdchange.inc"
00029 };
00030
00031
00032 static int do_help(CBM_FILE fd, char *argv[]);
00033
00034
00035
00036
00037 static int do_version(CBM_FILE fd, char *argv[])
00038 {
00039 printf("cbmctrl version " OPENCBM_VERSION ", built on " __DATE__ " at " __TIME__ "\n");
00040
00041 return 0;
00042 }
00043
00044
00045
00046
00047 static int do_lock(CBM_FILE fd, char *argv[])
00048 {
00049 cbm_lock(fd);
00050 return 0;
00051 }
00052
00053
00054
00055
00056 static int do_unlock(CBM_FILE fd, char *argv[])
00057 {
00058 cbm_unlock(fd);
00059 return 0;
00060 }
00061
00062
00063
00064
00065 static int do_reset(CBM_FILE fd, char *argv[])
00066 {
00067 return cbm_reset(fd);
00068 }
00069
00070
00071
00072
00073 static int do_listen(CBM_FILE fd, char *argv[])
00074 {
00075 return cbm_listen(fd, arch_atoc(argv[0]), arch_atoc(argv[1]));
00076 }
00077
00078
00079
00080
00081 static int do_talk(CBM_FILE fd, char *argv[])
00082 {
00083 return cbm_talk(fd, arch_atoc(argv[0]), arch_atoc(argv[1]));
00084 }
00085
00086
00087
00088
00089 static int do_unlisten(CBM_FILE fd, char *argv[])
00090 {
00091 return cbm_unlisten(fd);
00092 }
00093
00094
00095
00096
00097 static int do_untalk(CBM_FILE fd, char *argv[])
00098 {
00099 return cbm_untalk(fd);
00100 }
00101
00102
00103
00104
00105 static int do_open(CBM_FILE fd, char *argv[])
00106 {
00107 return cbm_open(fd, arch_atoc(argv[0]), arch_atoc(argv[1]), argv[2], strlen(argv[2]));
00108 }
00109
00110
00111
00112
00113 static int do_open_p(CBM_FILE fd, char *argv[])
00114 {
00115 cbm_ascii2petscii(argv[2]);
00116 return do_open(fd, argv);
00117 }
00118
00119
00120
00121
00122 static int do_close(CBM_FILE fd, char *argv[])
00123 {
00124 return cbm_close(fd, arch_atoc(argv[0]), arch_atoc(argv[1]));
00125 }
00126
00127
00128
00129
00130 static int do_read(CBM_FILE fd, char *argv[])
00131 {
00132 int size, rv = 0;
00133 unsigned char buf[2048];
00134 FILE *f;
00135
00136 if(argv[0] && strcmp(argv[0],"-") != 0)
00137 {
00138
00139
00140 f = fopen(argv[0], "wb");
00141 }
00142 else
00143 {
00144
00145
00146 f = arch_fdopen(arch_fileno(stdout), "wb");
00147
00148
00149
00150 arch_setbinmode(arch_fileno(stdout));
00151 }
00152
00153 if(!f)
00154 {
00155 arch_error(0, arch_get_errno(), "could not open output file: %s",
00156 (argv[0] && strcmp(argv[0], "-") != 0) ? argv[0] : "stdout");
00157 return 1;
00158 }
00159
00160
00161 while(0 < (size = cbm_raw_read(fd, buf, sizeof(buf))))
00162 {
00163
00164 if(size != (int) fwrite(buf, 1, size, f))
00165 {
00166 rv=1;
00167 break;
00168 }
00169
00170 }
00171
00172 if(size < 0) rv=1;
00173
00174 fclose(f);
00175 return rv;
00176 }
00177
00178
00179
00180
00181 static int do_write(CBM_FILE fd, char *argv[])
00182 {
00183 char *fn;
00184 int size;
00185 unsigned char buf[2048];
00186 FILE *f;
00187
00188 if(!argv[0] || strcmp(argv[0], "-") == 0 || strcmp(argv[0], "") == 0)
00189 {
00190 fn = "(stdin)";
00191 f = stdin;
00192
00193
00194
00195 arch_setbinmode(arch_fileno(stdin));
00196 }
00197 else
00198 {
00199 off_t filesize;
00200
00201 fn = argv[0];
00202 f = fopen(argv[0], "rb");
00203 if(f == NULL)
00204 {
00205 arch_error(0, arch_get_errno(), "could not open %s", fn);
00206 return 1;
00207 }
00208 if(arch_filesize(argv[0], &filesize))
00209 {
00210 arch_error(0, arch_get_errno(), "could not stat %s", fn);
00211 return 1;
00212 }
00213 }
00214
00215
00216 size = fread(buf, 1, sizeof(buf), f);
00217
00218 if(size == 0 && feof(f))
00219 {
00220 arch_error(0, 0, "no data: %s", fn);
00221 if(f != stdin) fclose(f);
00222 return 1;
00223 }
00224
00225
00226 while( ! ferror(f))
00227 {
00228
00229 if(size != cbm_raw_write(fd, buf, size))
00230 {
00231
00232 break;
00233 }
00234
00235
00236 size = fread(buf, 1, sizeof(buf), f);
00237 if(size == 0 && feof(f))
00238 {
00239
00240 if(f != stdin) fclose(f);
00241 return 0;
00242 }
00243 }
00244
00245 if(ferror(f))
00246 {
00247 arch_error(0, 0, "could not read %s", fn);
00248 }
00249
00250
00251 if(f != stdin) fclose(f);
00252 return 1;
00253 }
00254
00255
00256
00257
00258 static int do_status(CBM_FILE fd, char *argv[])
00259 {
00260 char buf[40];
00261 char unit;
00262 int rv;
00263
00264 unit = arch_atoc(argv[0]);
00265
00266 rv = cbm_device_status(fd, unit, buf, sizeof(buf));
00267 printf("%s", cbm_petscii2ascii(buf));
00268
00269 return (rv == 99) ? 1 : 0;
00270 }
00271
00272
00273
00274
00275 static int do_command(CBM_FILE fd, char *argv[])
00276 {
00277 int rv;
00278
00279 rv = cbm_listen(fd, arch_atoc(argv[0]), 15);
00280 if(rv == 0)
00281 {
00282 cbm_raw_write(fd, argv[1], strlen(argv[1]));
00283 rv = cbm_unlisten(fd);
00284 }
00285 return rv;
00286 }
00287
00288
00289
00290
00291 static int do_command_p(CBM_FILE fd, char *argv[])
00292 {
00293 cbm_ascii2petscii(argv[1]);
00294 return do_command(fd, argv);
00295 }
00296
00297
00298
00299
00300 static int do_dir(CBM_FILE fd, char *argv[])
00301 {
00302 char c, buf[40];
00303 int rv;
00304 char unit;
00305
00306 unit = arch_atoc(argv[0]);
00307 rv = cbm_open(fd, unit, 0, "$", strlen("$"));
00308 if(rv == 0)
00309 {
00310 if(cbm_device_status(fd, unit, buf, sizeof(buf)) == 0)
00311 {
00312 cbm_talk(fd, unit, 0);
00313 if(cbm_raw_read(fd, buf, 2) == 2)
00314 {
00315 while(cbm_raw_read(fd, buf, 2) == 2)
00316 {
00317 if(cbm_raw_read(fd, buf, 2) == 2)
00318 {
00319 printf("%u ", (unsigned char)buf[0] | (unsigned char)buf[1] << 8 );
00320 while((cbm_raw_read(fd, &c, 1) == 1) && c)
00321 {
00322 putchar(cbm_petscii2ascii_c(c));
00323 }
00324 putchar('\n');
00325 }
00326 }
00327 cbm_untalk(fd);
00328 cbm_device_status(fd, unit, buf, sizeof(buf));
00329 printf("%s", cbm_petscii2ascii(buf));
00330 }
00331 else
00332 {
00333 cbm_untalk(fd);
00334 }
00335
00336 }
00337 else
00338 {
00339 printf("%s", cbm_petscii2ascii(buf));
00340 }
00341 cbm_close(fd, unit, 0);
00342 }
00343 return rv;
00344 }
00345
00346
00347
00348
00349 static int do_download(CBM_FILE fd, char *argv[])
00350 {
00351 unsigned char unit;
00352 unsigned short c;
00353 int addr, count, i, rv = 0;
00354 char *tail, buf[32], cmd[7];
00355 FILE *f;
00356
00357 unit = arch_atoc(argv[0]);
00358
00359 addr = strtol(argv[1], &tail, 0);
00360 if(addr < 0 || addr > 0xffff || *tail)
00361 {
00362 arch_error(0, 0, "invalid address: %s", argv[1]);
00363 return 1;
00364 }
00365
00366 count = strtol(argv[2], &tail, 0);
00367 if((count + addr) > 0x10000 || *tail)
00368 {
00369 arch_error(0, arch_get_errno(), "invalid byte count %s", argv[2]);
00370 return 1;
00371 }
00372
00373 if(argv[3] && strcmp(argv[3],"-") != 0)
00374 {
00375
00376
00377 f = fopen(argv[3], "wb");
00378 }
00379 else
00380 {
00381
00382
00383 f = arch_fdopen(arch_fileno(stdout), "wb");
00384
00385
00386
00387 arch_setbinmode(arch_fileno(stdout));
00388 }
00389
00390 if(!f)
00391 {
00392 arch_error(0, arch_get_errno(), "could not open output file: %s",
00393 (argv[3] && strcmp(argv[3], "-") != 0) ? argv[3] : "stdout");
00394 return 1;
00395 }
00396
00397 for(i = 0; (rv == 0) && (i < count); i+=32)
00398 {
00399 c = count - i;
00400 if(c > 32)
00401 {
00402 c = 32;
00403 }
00404 sprintf(cmd, "M-R%c%c%c", addr%256, addr/256, c);
00405 cbm_listen(fd, unit, 15);
00406 rv = cbm_raw_write(fd, cmd, 6) == 6 ? 0 : 1;
00407 cbm_unlisten(fd);
00408 if(rv == 0)
00409 {
00410 addr += c;
00411 cbm_talk(fd, unit, 15);
00412 rv = cbm_raw_read(fd, buf, c) == c ? 0 : 1;
00413 cbm_untalk(fd);
00414 if(rv == 0)
00415 {
00416 fwrite(buf, 1, c, f);
00417 }
00418 }
00419 }
00420 fclose(f);
00421 return rv;
00422 }
00423
00424
00425
00426
00427 static int do_upload(CBM_FILE fd, char *argv[])
00428 {
00429 unsigned char unit;
00430 int addr;
00431 int rv;
00432 size_t size;
00433 char *tail, *fn;
00434 unsigned char addr_buf[2];
00435 unsigned int buflen = 65537;
00436 unsigned char *buf;
00437 FILE *f;
00438
00439 buf = malloc(buflen);
00440 if (!buf)
00441 {
00442 fprintf(stderr, "Not enough memory for buffer.\n");
00443 return 1;
00444 }
00445
00446 unit = arch_atoc(argv[0]);
00447
00448 addr = strtoul(argv[1], &tail, 0);
00449 if(addr < -1 || addr > 0xffff || *tail)
00450 {
00451 arch_error(0, 0, "invalid address: %s", argv[1]);
00452 free(buf);
00453 return 1;
00454 }
00455
00456 if(!argv[2] || strcmp(argv[2], "-") == 0 || strcmp(argv[2], "") == 0)
00457 {
00458 fn = "(stdin)";
00459 f = stdin;
00460
00461
00462
00463 arch_setbinmode(arch_fileno(stdin));
00464 }
00465 else
00466 {
00467 off_t filesize;
00468
00469 fn = argv[2];
00470 f = fopen(argv[2], "rb");
00471 if(f == NULL)
00472 {
00473 arch_error(0, arch_get_errno(), "could not open %s", fn);
00474 free(buf);
00475 return 1;
00476 }
00477 if(arch_filesize(argv[2], &filesize))
00478 {
00479 arch_error(0, arch_get_errno(), "could not stat %s", fn);
00480 free(buf);
00481 return 1;
00482 }
00483 }
00484
00485 if(addr == -1)
00486 {
00487
00488 if(fread(addr_buf, 2, 1, f) != 1)
00489 {
00490 arch_error(0, arch_get_errno(), "could not read %s", fn);
00491 if(f != stdin) fclose(f);
00492 free(buf);
00493 return 1;
00494 }
00495
00496
00497
00498 addr = addr_buf[0] | (addr_buf[1] << 8);
00499 }
00500
00501 size = fread(buf, 1, buflen, f);
00502 if(ferror(f))
00503 {
00504 arch_error(0, 0, "could not read %s", fn);
00505 if(f != stdin) fclose(f);
00506 free(buf);
00507 return 1;
00508 }
00509 else if(size == 0 && feof(f))
00510 {
00511 arch_error(0, 0, "no data: %s", fn);
00512 if(f != stdin) fclose(f);
00513 free(buf);
00514 return 1;
00515 }
00516
00517 if(addr + size > 0x10000)
00518 {
00519 arch_error(0, 0, "program too big: %s", fn);
00520 if (f != stdin) fclose(f);
00521 free(buf);
00522 return 1;
00523 }
00524
00525 if(f != stdin) fclose(f);
00526
00527 rv = (cbm_upload(fd, unit, addr, buf, size) == (int)size) ? 0 : 1;
00528
00529 free(buf);
00530
00531 return rv;
00532 }
00533
00534
00535
00536
00537 static int do_detect(CBM_FILE fd, char *argv[])
00538 {
00539 unsigned int num_devices;
00540 unsigned char device;
00541 const char *type_str;
00542
00543 num_devices = 0;
00544
00545 for( device = 8; device < 16; device++ )
00546 {
00547 enum cbm_device_type_e device_type;
00548 if( cbm_identify( fd, device, &device_type, &type_str ) == 0 )
00549 {
00550 enum cbm_cable_type_e cable_type;
00551 const char *cable_str = "(cannot determine cable type)";
00552
00553 num_devices++;
00554
00555 if ( cbm_identify_xp1541( fd, device, &device_type, &cable_type ) == 0 )
00556 {
00557 switch (cable_type)
00558 {
00559 case cbm_ct_none:
00560 cable_str = "";
00561 break;
00562
00563 case cbm_ct_xp1541:
00564 cable_str = "(XP1541)";
00565 break;
00566
00567 case cbm_ct_unknown:
00568 default:
00569 break;
00570 }
00571 }
00572 printf( "%2d: %s %s\n", device, type_str, cable_str );
00573 }
00574 }
00575 arch_set_errno(0);
00576 return num_devices > 0 ? 0 : 1;
00577 }
00578
00579
00580
00581
00582 static int do_change(CBM_FILE fd, char *argv[])
00583 {
00584 unsigned char unit;
00585 int rv;
00586
00587 unit = arch_atoc(argv[0]);
00588
00589 do
00590 {
00591
00592
00593
00594
00595
00596
00597
00598
00599 enum cbm_device_type_e device_type;
00600
00601 if (cbm_identify(fd, unit, &device_type, NULL) == 0)
00602 {
00603 if (device_type == cbm_dt_cbm1581)
00604 {
00605 fprintf(stderr, "Drive %u is a 1581, which is not supported (yet).\n", unit);
00606 rv = 1;
00607 break;
00608 }
00609 }
00610
00611
00612
00613
00614 if (cbm_exec_command(fd, unit, "I0:", 0) != 0)
00615 {
00616
00617
00618
00619
00620 rv = 1;
00621 break;
00622 }
00623
00624 rv = cbm_upload(fd, unit, 0x500, prog_tdchange, sizeof(prog_tdchange));
00625
00626 if (rv != sizeof(prog_tdchange))
00627 {
00628 rv = 1;
00629 break;
00630 }
00631
00632 cbm_exec_command(fd, unit, "U3:", 0);
00633 cbm_iec_release(fd, IEC_ATN | IEC_DATA | IEC_CLOCK | IEC_RESET);
00634
00635
00636
00637
00638 cbm_iec_wait(fd, IEC_DATA, 1);
00639
00640
00641
00642
00643
00644 cbm_iec_wait(fd, IEC_CLOCK, 1);
00645
00646
00647
00648
00649 cbm_iec_set(fd, IEC_ATN);
00650
00651
00652
00653
00654 cbm_iec_wait(fd, IEC_CLOCK, 0);
00655
00656
00657
00658
00659 cbm_iec_release(fd, IEC_ATN);
00660
00661 } while (0);
00662
00663 return rv;
00664 }
00665
00666 struct prog
00667 {
00668 int need_driver;
00669 char *name;
00670 mainfunc prog;
00671 int req_args_min;
00672 int req_args_max;
00673 char *arglist;
00674 char *shorthelp_text;
00675 char *help_text;
00676 };
00677
00678 static struct prog prog_table[] =
00679 {
00680 {0, "--help" , do_help , 0, 1, "[<command>]",
00681 "output this help screen",
00682 "This command outputs some help information for cbmctrl.\n\n"
00683 "<command> is the (optional) command to get information about.\n\n"
00684 "If you use it without parameter, it outputs a list of all\n"
00685 "available commands." },
00686
00687 {0, "-h" , do_help , 0, 1, "",
00688 "same as --help",
00689 "for more info, use \"cbmctrl --help --help\"." },
00690
00691 {0, "--version",do_version , 0, 0, "",
00692 "output version information",
00693 "This command just outputs the version number and\n"
00694 "build date of cbmctrl." },
00695
00696 {0, "-V" , do_version , 0, 0, "",
00697 "same as --version",
00698 "for more info, use \"cbmctrl --help --version\"." },
00699
00700 {1, "lock" , do_lock , 0, 0, "",
00701 "Lock the parallel port for the use by cbm4win/cbm4linux.",
00702 "This command locks the parallel port for the use by cbm4win/cbm4linux,\n"
00703 "so that sequences of e.g. talk/read/untalk commands are not broken by\n"
00704 "concurrent processes wanting to access the parallel port." },
00705
00706 {1, "unlock" , do_unlock , 0, 0, "",
00707 "Unlock the parallel port for the use by cbm4win/cbm4linux.",
00708 "This command unlocks the parallel port again so that other processes\n"
00709 "get a chance to access the parallel port." },
00710
00711 {1, "listen" , do_listen , 2, 2, "<device> <secadr>",
00712 "perform a listen on the IEC bus",
00713 "Output a listen command on the IEC bus.\n"
00714 "<device> is the device number,\n"
00715 "<secadr> the secondary address to use for this.\n\n"
00716 "This has to be undone later with an unlisten command." },
00717
00718 {1, "talk" , do_talk , 2, 2, "<device> <secadr>",
00719 "perform a talk on the IEC bus",
00720 "Output a talk command on the IEC bus.\n"
00721 "<device> is the device number,\n"
00722 "<secadr> the secondary address to use for this.\n\n"
00723 "This has to be undone later with an untalk command." },
00724
00725 {1, "unlisten", do_unlisten, 0, 0, "",
00726 "perform an unlisten on the IEC bus",
00727 "Undo one or more previous listen commands.\n"
00728 "This affects all drives." },
00729
00730 {1, "untalk" , do_untalk , 0, 0, "",
00731 "perform an untalk on the IEC bus",
00732 "Undo one or more previous talk commands.\n"
00733 "This affects all drives." },
00734
00735 {1, "open" , do_open , 3, 3, "<device> <secadr> <filename>",
00736 "perform an open on the IEC bus",
00737 "Output an open command on the IEC bus.\n"
00738 "<device> is the device number,\n"
00739 "<secadr> the secondary address to use for this.\n"
00740 "<filename> is the name of the file to be opened.\n\n"
00741 "This has to be undone later with a close command.\n\n"
00742 "NOTE: You cannot do an open without a filename.\n"
00743 " Although a CBM machine (i.e., a C64) allows this,\n"
00744 " this is an internal operation to the computer only." },
00745
00746 {1, "popen" , do_open_p , 3, 3, "<device> <secadr> <filename>",
00747 "same as open, but convert the filename from ASCII to PETSCII.",
00748 "Output an open command on the IEC bus.\n"
00749 "<device> is the device number,\n"
00750 "<secadr> the secondary address to use for this.\n"
00751 "<filename> is the name of the file to be opened.\n\n"
00752 "This has to be undone later with a close command.\n\n"
00753 "NOTE: You cannot do an open without a filename.\n"
00754 " Although a CBM machine (i.e., a C64) allows this,\n"
00755 " this is an internal operation to the computer only." },
00756
00757 {1, "close" , do_close , 2, 2, "<device> <secadr>",
00758 "perform a close on the IEC bus",
00759 "Undo a previous open command." },
00760
00761 {1, "read" , do_read , 0, 1, "[<file>]",
00762 "read raw data from the IEC bus",
00763 "With this command, you can read raw data from the IEC bus.\n"
00764 "<file> (optional) file name of a file to write the contents to.\n"
00765 " If this name is not given or it is a dash ('-'), the\n"
00766 " contents will be written to stdout, normally the console." },
00767
00768 {1, "write" , do_write , 0, 1, "[<file>]",
00769 "write raw data to the IEC bus",
00770 "With this command, you can write raw data to the IEC bus.\n"
00771 "<file> (optional) file name of a file to read the values from.\n"
00772 " If this name is not given or it is a dash ('-'), the\n"
00773 " contents will be read from stdin, normally the console." },
00774
00775 {1, "status" , do_status , 1, 1, "<device>",
00776 "give the status of the specified drive",
00777 "This command gets the status (the so-called 'error channel')"
00778 "of the given drive and outputs it on the screen.\n"
00779 "<device> is the device number of the drive." },
00780
00781 {1, "command" , do_command , 2, 2, "<device> <cmdstr>",
00782 "issue a command to the specified drive",
00783 "This command issues a command to a specific drive.\n"
00784 "This command is a command that you normally give to\n"
00785 "channel 15 (i.e., N: to format a drive, V: to validate, etc.).\n\n"
00786 "<device> is the device number of the drive.\n\n"
00787 "<cmdstr> is the command to execute in the drive.\n"
00788 "NOTE: You have to give the commands in upper-case letters.\n"
00789 " Lower case will NOT work!" },
00790
00791 {1, "pcommand", do_command_p, 2, 2, "<device> <cmdstr>",
00792 "same as command, but convert the cmdstr from ASCII to PETSCII.",
00793 "This command issues a command to a specific drive.\n"
00794 "This command is a command that you normally give to\n"
00795 "channel 15 (i.e., n: to format a drive, v: to validate, etc.).\n\n"
00796 "<device> is the device number of the drive.\n\n"
00797 "<cmdstr> is the command to execute in the drive.\n"
00798 "NOTE: You have to give the commands in lower-case letters.\n"
00799 " Upper case will NOT work!" },
00800
00801 {1, "dir" , do_dir , 1, 1, "<device>",
00802 "output the directory of the disk in the specified drive",
00803 "This command gets the directory of the disk in the drive.\n\n"
00804 "<device> is the device number of the drive." },
00805
00806 {1, "download", do_download, 3, 4, "<device> <adr> <count> [<file>]",
00807 "download memory contents from the floppy drive",
00808 "With this command, you can get data from the floppy drive memory.\n"
00809 "<device> is the device number of the drive.\n"
00810 "<adr> is the starting address of the memory region to get.\n"
00811 " it can be given in decimal or in hex (with a 0x prefix).\n"
00812 "<count> is the number of bytes to read.\n"
00813 " it can be given in decimal or in hex (with a 0x prefix).\n"
00814 "<file> (optional) file name of a file to write the contents to.\n"
00815 " If this name is not given or it is a dash ('-'), the\n"
00816 " contents will be written to stdout, normally the console.\n\n"
00817 "Example:\n"
00818 " cbmctrl download 8 0xc000 0x4000 1541ROM.BIN\n"
00819 " * reads the 1541 ROM (from $C000 to $FFFF) from drive 8 into 1541ROM.BIN" },
00820
00821 {1, "upload" , do_upload , 2, 3, "<device> <adr> [<file>]",
00822 "upload memory contents to the floppy drive",
00823 "With this command, you can write data to the floppy drive memory.\n"
00824 "<device> is the device number of the drive.\n"
00825 "<adr> is the starting address of the memory region to write to.\n"
00826 " it can be given in decimal or in hex (with a 0x prefix).\n"
00827 "<file> (optional) file name of a file to read the values from.\n"
00828 " If this name is not given or it is a dash ('-'), the\n"
00829 " contents will be read from stdin, normally the console."
00830 "Example:\n"
00831 " cbmctrl upload 8 0x500 BUFFER2.BIN\n"
00832 " * writes the file BUFFER2.BIN to drive 8, address $500." },
00833
00834 {1, "reset" , do_reset , 0, 0, "",
00835 "reset all drives on the IEC bus",
00836 "This command performs a (physical) reset of all drives on the IEC bus." },
00837
00838 {1, "detect" , do_detect , 0, 0, "",
00839 "detect all drives on the IEC bus",
00840 "This command tries to detect all drives on the IEC bus.\n"
00841 "For this, this command access all possible drives and tries to read\n"
00842 "some bytes from its memory. If a drive is detected, its name is output.\n"
00843 "Additionally, this routine determines if the drive is connected via a\n"
00844 "parallel cable (XP1541 companion cable)." },
00845
00846 {1, "change" , do_change , 1, 1, "<device>",
00847 "wait for a disk to be changed in the specified drive",
00848 "This command waits for a disk to be changed in the specified drive.\n\n"
00849 "For this, it makes the following assumptions:\n\n"
00850 "* there is already a disk in the drive.\n"
00851 "* that disk will be removed and replaced by another disk.\n"
00852 "* we do not want to return from this command until the disk is completely\n"
00853 " inserted and ready to be read/written.\n\n"
00854 "Because of this, just opening the drive and closing it again (without\n"
00855 "actually removing the disk) will not work in most cases." },
00856
00857 {0, NULL,NULL}
00858 };
00859
00860 static struct prog *find_main(char *name)
00861 {
00862 int i;
00863
00864 for(i=0; prog_table[i].name; i++)
00865 {
00866 if(strcmp(name, prog_table[i].name) == 0)
00867 {
00868 return &prog_table[i];
00869 }
00870 }
00871 return NULL;
00872 }
00873
00874
00875
00876
00877 static int do_help(CBM_FILE fd, char *argv[])
00878 {
00879 int i;
00880
00881 do_version(fd, argv);
00882
00883 printf("\n");
00884
00885 if (*argv == 0)
00886 {
00887 for(i=0; prog_table[i].prog; i++)
00888 {
00889 printf(" %-9s %s\n", prog_table[i].name, prog_table[i].shorthelp_text);
00890 }
00891
00892 printf("\nFor more information on a specific command, try --help <COMMAND>.\n");
00893
00894 }
00895 else
00896 {
00897 struct prog *p;
00898
00899 p = find_main(argv[0]);
00900
00901 if (p)
00902 {
00903 printf(" cbmctrl %s %s\n\n %s\n\n%s\n", p->name, p->arglist, p->shorthelp_text, p->help_text);
00904 }
00905 else
00906 {
00907 printf(" Nothing known about \"cbmctrl %s\".\n", argv[0]);
00908 }
00909 }
00910
00911
00912 return 0;
00913 }
00914
00915 int ARCH_MAINDECL main(int argc, char *argv[])
00916 {
00917 struct prog *p;
00918
00919 p = argc < 2 ? NULL : find_main(argv[1]);
00920 if(p)
00921 {
00922 if((p->req_args_min <= argc-2) && (p->req_args_max >= argc-2))
00923 {
00924 CBM_FILE fd;
00925 int rv;
00926
00927 if(p->need_driver)
00928 rv = cbm_driver_open(&fd, 0);
00929 else
00930 rv = 0;
00931
00932 if(rv == 0)
00933 {
00934 rv = p->prog(fd, &argv[2]) != 0;
00935 if(rv && arch_get_errno())
00936 {
00937 arch_error(0, arch_get_errno(), "%s", argv[1]);
00938 }
00939
00940 if(p->need_driver)
00941 cbm_driver_close(fd);
00942 }
00943 else
00944 {
00945 if(arch_get_errno())
00946 {
00947 arch_error(0, arch_get_errno(), "%s", cbm_get_driver_name(0));
00948 }
00949 rv = 1;
00950 }
00951 return rv;
00952 }
00953 else
00954 {
00955 fprintf(stderr, "wrong number of arguments:\n\n %s %s %s\n",
00956 argv[0], argv[1], p->arglist);
00957 }
00958 }
00959 else
00960 {
00961 printf("invalid command. For info on possible commands, try the --help parameter.\n\n");
00962 }
00963 return 2;
00964 }