home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 1.2 / amidev_cd_12.iso / reference_library / devices / dev_examples / track_copy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-20  |  9.0 KB  |  333 lines

  1. /*
  2.  * Track_Copy.c
  3.  *
  4.  * This program does a track by track copy from one drive to another
  5.  *
  6.  * Compile with SAS C 5.10  LC -cfist -ms -v -L
  7.  *
  8.  * This program will only run from the CLI.  If started from
  9.  * the workbench, it will just exit...
  10.  *
  11.  * Usage:  trackcopy  dfx dfy
  12.  */
  13.  
  14. #include <exec/types.h>
  15. #include <exec/memory.h>
  16. #include <devices/trackdisk.h>
  17. #include <dos/dosextens.h> */
  18.  
  19. #include <clib/exec_protos.h>
  20. #include <clib/alib_protos.h>
  21. #include <clib/dos_protos.h>
  22.  
  23. #include <stdio.h>
  24. #include <string.h>
  25.  
  26. #ifdef LATTICE
  27. int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
  28. int chkabort(void) { return(0); }  /* really */
  29. #endif
  30.  
  31. #define TRACK_SIZE      ((LONG)(NUMSECS * TD_SECTOR))
  32.  
  33.  
  34. /*
  35.  * Turn the BUSY flag off/on for the drive
  36.  * If onflag is TRUE, the disk will be marked as busy...
  37.  *
  38.  * This is to stop the validator from executing while
  39.  * we are playing with the disks.
  40.  */
  41. VOID disk_busy(UBYTE *drive,LONG onflag)
  42. {
  43. struct StandardPacket *pk;
  44. struct Process        *tsk;
  45.  
  46.     tsk=(struct Process *)FindTask(NULL);
  47.     if (pk=AllocMem(sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR))
  48.     {
  49.         pk->sp_Msg.mn_Node.ln_Name=(UBYTE *)&(pk->sp_Pkt);
  50.  
  51.         pk->sp_Pkt.dp_Link=&(pk->sp_Msg);
  52.         pk->sp_Pkt.dp_Port=&(tsk->pr_MsgPort);
  53.         pk->sp_Pkt.dp_Type=ACTION_INHIBIT;
  54.         pk->sp_Pkt.dp_Arg1=(onflag ? -1L : 0L);
  55.  
  56.         PutMsg(DeviceProc(drive),(struct Message *)pk);
  57.         WaitPort(&(tsk->pr_MsgPort));
  58.         GetMsg(&(tsk->pr_MsgPort));
  59.         FreeMem(pk,(long)sizeof(*pk));
  60.     }
  61. }
  62.  
  63. /*
  64.  * This turns the motor off
  65.  */
  66. VOID Motor_Off(struct IOExtTD *disk)
  67. {
  68.     disk->iotd_Req.io_Length=0;
  69.     disk->iotd_Req.io_Command=TD_MOTOR;
  70.     DoIO((struct IORequest *)disk);
  71. }
  72.  
  73. /*
  74.  * This turns the motor on
  75.  */
  76. VOID    Motor_On(struct IOExtTD *disk)
  77. {
  78.     disk->iotd_Req.io_Length=1;
  79.     disk->iotd_Req.io_Command=TD_MOTOR;
  80.     DoIO((struct IORequest *)disk);
  81. }
  82.  
  83. /*
  84.  * This reads a track, reporting any errors...
  85.  */
  86.  
  87. SHORT Read_Track(struct IOExtTD *disk,UBYTE *buffer,SHORT track)
  88. {
  89. SHORT All_OK=TRUE;
  90.  
  91.     disk->iotd_Req.io_Length=TRACK_SIZE;
  92.     disk->iotd_Req.io_Data=(APTR)buffer;
  93.     disk->iotd_Req.io_Command=CMD_READ;
  94.     disk->iotd_Req.io_Offset=(ULONG)(TRACK_SIZE * track);
  95.     DoIO((struct IORequest *)disk);
  96.     if (disk->iotd_Req.io_Error)
  97.     {
  98.         All_OK=FALSE;
  99.         printf("Error %u when reading track %d",disk->iotd_Req.io_Error,track);
  100.     }
  101.     return(All_OK);
  102. }
  103.  
  104.  
  105. /*
  106.  * This writes a track, reporting any errors...
  107.  */
  108.  
  109. SHORT Write_Track(struct IOExtTD *disk,UBYTE *buffer,SHORT track)
  110. {
  111. SHORT All_OK=TRUE;
  112.  
  113.     disk->iotd_Req.io_Length=TRACK_SIZE;
  114.     disk->iotd_Req.io_Data=(APTR)buffer;
  115.     disk->iotd_Req.io_Command=TD_FORMAT;
  116.     disk->iotd_Req.io_Offset=(ULONG)(TRACK_SIZE * track);
  117.     DoIO((struct IORequest *)disk);
  118.     if (disk->iotd_Req.io_Error)
  119.     {
  120.         All_OK=FALSE;
  121.         printf("Error %d when writing track %d",disk->iotd_Req.io_Error,track);
  122.     }
  123.     return(All_OK);
  124. }
  125.  
  126. /*
  127.  * This function finds the number of TRACKS on the device.
  128.  * NOTE That this is TRACKS and not cylinders.  On a Two-Head
  129.  * drive (such as the standard 3.5" drives) the number of tracks
  130.  * is 160, 80 cylinders, 2-heads.
  131.  */
  132.  
  133. SHORT FindNumTracks(struct IOExtTD *disk)
  134. {
  135.     disk->iotd_Req.io_Command=TD_GETNUMTRACKS;
  136.     DoIO((struct IORequest *)disk);
  137.     return((SHORT)disk->iotd_Req.io_Actual);
  138. }
  139.  
  140. /*
  141.  * This routine allocates the memory for one track and does
  142.  * the copy loop.
  143.  */
  144.  
  145. VOID Do_Copy(struct IOExtTD *diskreq0,struct IOExtTD *diskreq1)
  146. {
  147. UBYTE *buffer;
  148. SHORT track;
  149. SHORT All_OK;
  150. SHORT NumTracks;
  151.  
  152.     if (buffer=AllocMem(TRACK_SIZE,MEMF_CHIP|MEMF_PUBLIC))
  153.     {
  154.         printf(" Starting Motors\r");
  155.         Motor_On(diskreq0);
  156.         Motor_On(diskreq1);
  157.         All_OK=TRUE;
  158.  
  159.         NumTracks=FindNumTracks(diskreq0);
  160.  
  161.         for (track=0;(track<NumTracks) && All_OK;track++)
  162.         {
  163.             printf(" Reading track %d\r",track);
  164.  
  165.             if (All_OK=Read_Track(diskreq0,buffer,track))
  166.             {
  167.                 printf(" Writing track %d\r",track);
  168.  
  169.                 All_OK=Write_Track(diskreq1,buffer,track);
  170.             }
  171.         }
  172.         if (All_OK) printf(" * Copy complete *");
  173.         printf("\n");
  174.         Motor_Off(diskreq0);
  175.         Motor_Off(diskreq1);
  176.         FreeMem(buffer,TRACK_SIZE);
  177.     }
  178.     else printf("No memory for track buffer...\n");
  179. }
  180.  
  181. /*
  182.  * Prompts the user to remove one of the disks.
  183.  * Since this program makes an EXACT copy of the disks
  184.  * AmigaDOS would get confused by them so one must be removed
  185.  * before the validator is let loose.  Also, note that the
  186.  * disks may NEVER be in drives on the SAME computer at the
  187.  * SAME time unless one of the disks is renamed.  This is due
  188.  * to a bug in the system.  It would normally be prevented
  189.  * by a diskcopy program that knew the disk format and modified
  190.  * the creation date by one clock-tick such that the disks would
  191.  * be different.
  192.  */
  193.  
  194. VOID Remove_Disks(VOID)
  195. {
  196.     printf("\nYou *MUST* remove at least one of the disks now.\n");
  197.     printf("\nPress RETURN when ready\n");
  198.     while(getchar()!='\n');
  199. }
  200.  
  201. /*
  202.  * Prompts the user to insert the disks.
  203.  */
  204.  
  205. VOID Insert_Disks(char drive1[], char drive2[])
  206. {
  207.     printf("\nPlease insert source disk in %s\n",drive1);
  208.     printf("\n          and destination in %s\n",drive2);
  209.     printf("\nPress RETURN when ready\n");
  210.     while(getchar()!='\n');
  211. }
  212.  
  213. /*
  214.  * Open the devices and mark them as busy
  215.  */
  216. VOID Do_OpenDevice(struct IOExtTD *diskreq0,struct IOExtTD *diskreq1, long unit[])
  217. {
  218. char drive1[] = "DFx:";  /* String for source drive */
  219. char drive2[] = "DFx:";  /* String for destination drive */
  220.  
  221.     drive1[2] = unit[0]+ '0';  /* Set drive number for source */
  222.  
  223.     if (!OpenDevice(TD_NAME,unit[0],(struct IORequest *)diskreq0,0L))
  224.     {
  225.           disk_busy(drive1,TRUE);
  226.           drive2[2] = unit[1]+ '0';  /* Set drive number for destination */
  227.  
  228.         if (!OpenDevice(TD_NAME,unit[1],(struct IORequest *)diskreq1,0L))
  229.         {
  230.             disk_busy(drive2,TRUE);
  231.  
  232.             Insert_Disks(drive1,drive2);
  233.             Do_Copy(diskreq0,diskreq1);
  234.             Remove_Disks();
  235.  
  236.             disk_busy(drive2,FALSE);
  237.             CloseDevice((struct IORequest *)diskreq1);
  238.         }
  239.         else printf("Could not open %s\n",drive2);
  240.  
  241.         disk_busy(drive1,FALSE);
  242.         CloseDevice((struct IORequest *)diskreq0);
  243.     }
  244.     else printf("Could not open %s\n",drive1);
  245. }
  246.  
  247.  
  248. SHORT ParseArgs(int argc, char **argv, long Unit[])
  249. #define OKAY 1
  250. {
  251. int j=1, params = OKAY;
  252. char *position[]={"First","Second"};
  253.  
  254. if (argc != 3)
  255.     {
  256.     printf("\nYou must specify a source and destination disk\n");
  257.     return(!OKAY);
  258.     }
  259. else if (strcmp(argv[1],argv[2]) == 0)
  260.            {
  261.            printf("\nYou must specify different disks for source and destination\n");
  262.            return(!OKAY);
  263.            }
  264.      else while (params == OKAY && j<3)
  265.            {
  266.            if (strnicmp(argv[j],"df",2)==0)
  267.              {
  268.              if (argv[j][2] >= '0' && argv[j][2] <= '3' && argv[j][3] == '\0')
  269.                {
  270.                Unit[j-1] = argv[j][2] - 0x30;
  271.                }
  272.              else
  273.                {
  274.                printf("\n%s parameter is wrong, unit number must be 0-3\n",position[j-1]);
  275.                params = !OKAY;
  276.                return(!OKAY);
  277.                }
  278.              }
  279.            else
  280.              {
  281.              printf("\n%s parameter is wrong, you must specify a floppy device df0 - df3\n",
  282.                      position[j-1]);
  283.              params=!OKAY;
  284.              return(!OKAY);
  285.              }
  286.            j++;
  287.            }
  288. return(OKAY);
  289. }
  290.  
  291.  
  292. VOID main(int argc,char **argv)
  293. {
  294. struct IOExtTD *diskreq0;
  295. struct IOExtTD *diskreq1;
  296. struct MsgPort *diskPort;
  297. long unit[2];
  298.  
  299.     if (ParseArgs(argc, argv, unit))       /* Check inputs */
  300.     {
  301.         if (diskPort=CreatePort(NULL,NULL))
  302.         {
  303.             if (diskreq0=(struct IOExtTD *)CreateExtIO(diskPort,
  304.                                                  sizeof(struct IOExtTD)))
  305.             {
  306.                 if (diskreq1=(struct IOExtTD *)CreateExtIO(diskPort,
  307.                                                  sizeof(struct IOExtTD)))
  308.                 {
  309.                     Do_OpenDevice(diskreq0,diskreq1, unit);
  310.                     DeleteExtIO((struct IORequest *)diskreq1);
  311.                 }
  312.                 else printf("Out of memory\n");
  313.                 DeleteExtIO((struct IORequest *)diskreq0);
  314.             }
  315.             else printf("Out of memory\n");
  316.             DeletePort(diskPort);
  317.         }
  318.         else printf("Could not create diskReq port\n");
  319.     }
  320. }
  321. /*
  322.    Only one per customer.
  323.    ----------------------
  324.    Since this example program makes an exact track-for-track duplicate,
  325.    AmigaDOS will get confused if both disks are in drives on the system
  326.    at the same time. While the disks are inhibited, this does not cause
  327.    a problem, but during normal operation, this will cause a system
  328.    hang. To prevent this, you can relabel one of the disks. A commercial
  329.    diskcopy program would have to understand the disk format and either
  330.    relabel the disk or modify the volume creation date/time by a bit in
  331.    order to make the disks look different to the system.
  332. */
  333.