home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer) / NeXT_Developer-3.3.iso / NextDeveloper / Examples / UNIX / Floppy / fdform.c next >
Encoding:
C/C++ Source or Header  |  1995-02-10  |  12.4 KB  |  542 lines

  1. /* fdform - Floppy format utility
  2.  *
  3.  *    usage:   fdform device [b=blocksize] [d=density] [g=gap3_length] 
  4.  *                [n=num_cylinders]
  5.  *
  6.  *        blocksize must be 512 or 1024.
  7.  *        density is in Kbytes. Current legal values are 720, 1440,
  8.  *            and 2880. Default is max density allowable for media.
  9.  *
  10.  *
  11.  *    You may freely copy, distribute and reuse the code in this example.
  12.  *    NeXT disclaims any warranty of any kind, expressed or implied, as to
  13.  *    its fitness for any particular use.
  14.  */
  15.  
  16. #import <fcntl.h>
  17. #import <stdio.h>
  18. #import <sys/types.h>
  19. #import <mach/mach.h>
  20. #import <bsd/dev/scsireg.h>
  21. /*
  22.  * m68k is worst case as far as alignment restrictions...
  23.  */
  24. #ifdef    m68k
  25. #import <bsd/dev/m68k/dma.h>
  26. #endif    m68k
  27. #import <sys/param.h>
  28. #import <signal.h>
  29. #import <bsd/dev/fd_extern.h>
  30. #import <libc.h>
  31. #import <stdlib.h>
  32. #import <sys/file.h>
  33.  
  34. void usage(char **argv);
  35. int format_disk(int fd, int live_fd, struct fd_format_info *finfop);
  36. int format_track(int fd, int cylinder, int head, 
  37.     struct fd_format_info *finfop);
  38. int recalibrate(int fd, struct fd_format_info *fip);
  39. int seek_com(int fd, int track, struct fd_format_info *finfop, int density);
  40. int do_ioc(int fd, fd_ioreq_t fdiop);
  41. int fd_rw(int fd,
  42.     int block,
  43.     int block_count,
  44.     u_char *addrs,
  45.     boolean_t read_flag,
  46.     struct fd_format_info *finfop);
  47. void format_abort();
  48.  
  49. #ifndef    TRUE
  50. #define TRUE    (1)
  51. #endif    TRUE
  52. #ifndef    FALSE
  53. #define FALSE    (0)
  54. #endif    FALSE
  55.  
  56. u_char             *vfy_buf;
  57. struct format_data     *fdp;
  58. int            cyls_to_format = 0;
  59. int             fmt_gap3_length = -1;
  60. int             fd;
  61. int            live_fd;
  62. struct fd_format_info     format_info;
  63.  
  64. int main(int argc, char *argv[])
  65. {
  66.     int             arg;
  67.     char             ch;
  68.     int             rtn;
  69.     kern_return_t         krtn;
  70.     int            format_data_size;
  71.     struct fd_sectsize_info *ssip;
  72.     int             density = FD_DENS_NONE;
  73.     int            blocksize = 512;
  74.     
  75.     if(argc<2) 
  76.         usage(argv);
  77.     fd = open(argv[1], O_RDWR, 0);
  78.     if(fd <= 0) {
  79.         printf("Opening %s:\n", argv[1]);
  80.         perror("open");
  81.         exit(1);
  82.     }
  83.     
  84.     /*
  85.      * Open the live partition for read/verify.
  86.      */
  87.     argv[1][strlen(argv[1]) - 1] = 'b';
  88.     live_fd = open(argv[1], O_RDONLY, 0);
  89.     if(live_fd <= 0) {
  90.         printf("Opening %s:\n", argv[1]);
  91.         perror("open");
  92.         exit(1);
  93.     }
  94.     for(arg=2; arg<argc; arg++) {
  95.         ch = argv[arg][0];
  96.         switch(ch) {
  97.             case 'd':
  98.                 density = atoi(&argv[arg][2]);
  99.             switch(density) {
  100.                 case 720:
  101.                     density = FD_DENS_1;
  102.                 break;
  103.                 case 1440:
  104.                     density = FD_DENS_2;
  105.                 break;
  106.                 case 2880:
  107.                     density = FD_DENS_4;
  108.                 break;
  109.                 default:
  110.                     usage(argv);
  111.             }
  112.             break;
  113.             case 'b':
  114.                 blocksize = atoi(&argv[arg][2]);
  115.             if((blocksize != 512) && (blocksize != 1024))
  116.                 usage(argv);
  117.             break;
  118.             
  119.             case 'g':
  120.                 fmt_gap3_length = atoi(&argv[arg][2]);
  121.             break;
  122.             
  123.             case 'n':
  124.                 cyls_to_format = atoi(&argv[arg][2]);
  125.             break;
  126.             
  127.             default:
  128.                 usage(argv);
  129.         }
  130.     }
  131.     /*
  132.      * find out what kind of disk is installed, then ensure that we
  133.      * haven't been asked to format a bogus density for this disk.
  134.      */
  135.     if(ioctl(fd, FDIOCGFORM, &format_info)) {
  136.         perror("ioctl(FDIOCGFORM)");
  137.         return(1);
  138.     }
  139.     if(density > format_info.disk_info.max_density) {
  140.         printf("\nMaximum Legal Density for this disk is ");
  141.         switch(format_info.disk_info.max_density) {
  142.             case FD_DENS_1:
  143.                 printf("1 (720 KBytes formatted)\n");
  144.             exit(1);
  145.             case FD_DENS_2:
  146.                 printf("2 (1.44 MByte formatted)\n");
  147.             exit(1);
  148.             case FD_DENS_4:
  149.                 printf("4 (2.88 MByte formatted)\n");
  150.             exit(1);
  151.         }
  152.     }
  153.     if(density == FD_DENS_NONE) 
  154.         density = format_info.disk_info.max_density;
  155.  
  156.     printf("Formatting disk %s: \n", argv[1]);
  157.     printf("    blocksize   = 0x%x\n", blocksize);
  158.     printf("    density     = ");
  159.     switch(density) {
  160.         case FD_DENS_1:
  161.             printf("720 KBytes\n");
  162.         break;
  163.         case FD_DENS_2:
  164.         printf("1.44 MByte\n");
  165.         break;
  166.         case FD_DENS_4:
  167.         printf("2.88 MByte\n");
  168.         break;
  169.     }    
  170.     /*
  171.      * If user hasn't specified gap length, use default provided by driver
  172.      */
  173.     if(fmt_gap3_length < 0)
  174.         fmt_gap3_length = format_info.sectsize_info.fmt_gap_length;
  175.     printf("    gap3 length = %d(d)\n", fmt_gap3_length);
  176.  
  177.     /*
  178.      * Generate a new format_info. Have the driver calculate physical 
  179.      * parameters based on sector size and density.  If we abort the 
  180.      * format for any reason, we'll mark the disk unformatted.
  181.      */
  182.     if(ioctl(fd, FDIOCSDENS, &density)) {
  183.         perror("ioctl(FDIOCSDENS)");
  184.         return(1);
  185.     }
  186.     if(ioctl(fd, FDIOCSSIZE, &blocksize)) {
  187.         perror("ioctl(FDIOCSSIZE)");
  188.         return(1);
  189.     }
  190.  
  191.     /*
  192.      * This returns all the current parameters, based on what we just
  193.      * told the driver.
  194.      */
  195.     if(ioctl(fd, FDIOCGFORM, &format_info)) {
  196.         perror("ioctl(FDIOCGFORM)");
  197.         format_abort();
  198.     }
  199.     
  200.     /*
  201.      * Get page-aligned buffers for all the reading and writing we'll 
  202.      * be doing.
  203.      */
  204.     ssip = &format_info.sectsize_info;
  205.     krtn = vm_allocate(task_self(), 
  206.             (vm_address_t *)&vfy_buf,
  207.             ssip->sects_per_trk * ssip->sect_size,
  208.             TRUE);
  209.     if(krtn) {
  210.         printf("\n...Couldn't allocate track buffer\n");
  211.         format_abort();
  212.     }
  213.     format_data_size = sizeof(struct format_data) * ssip->sects_per_trk;
  214.     krtn = vm_allocate(task_self(), 
  215.             (vm_address_t *)&fdp,
  216.             format_data_size,
  217.             TRUE);
  218.     if(krtn) {
  219.         printf("\n...Couldn't allocate Format data buffer\n");
  220.         format_abort();
  221.     }
  222.  
  223.     signal(SIGINT, format_abort);
  224.     if ((rtn = format_disk(fd, live_fd, &format_info)))
  225.         format_abort();
  226.     
  227.     printf("\n..Format Complete\n");
  228.     exit(0);
  229. }
  230.  
  231. void usage(char **argv) {
  232.     printf("usage: %s device [b=blocksize)] [d=density] [g=gap3_length] [n=num_cylinders]\n", argv[0]);
  233.     printf("       blocksize = 512 or 1024\n");
  234.     printf("       density = 720, 1440, 2880\n");
  235.     exit(1);
  236. }
  237.  
  238. void format_abort()
  239. {
  240.     int arg;
  241.     
  242.     /*
  243.      * ctl C or error abort; mark disk as unformatted.
  244.      */
  245.     arg = FD_DENS_NONE;
  246.     if(ioctl(fd, FDIOCSDENS, &arg)) {    /* unformatted */
  247.         perror("ioctl(FDIOCSDENS)");
  248.         exit(1);
  249.     }
  250.     printf("\n..Format Aborted\n");
  251.     exit(1);
  252.  
  253. }
  254. int format_disk(int fd, int live_fd, struct fd_format_info *finfop)
  255. {
  256.     int rtn;
  257.     int cylinder;
  258.     int head;
  259.     int vfy_block=0;
  260.     struct fd_sectsize_info *ssip = &finfop->sectsize_info;
  261.     
  262.     if(cyls_to_format == 0)
  263.         cyls_to_format = format_info.disk_info.num_cylinders;
  264.         
  265.     if ((rtn = recalibrate(fd, &format_info))) {
  266.         return(1);
  267.     }
  268.     for(cylinder=0; cylinder<cyls_to_format; cylinder++) {
  269.         for(head=0; 
  270.             head<format_info.disk_info.tracks_per_cyl; 
  271.             head++) {
  272.             if ((rtn = format_track(fd, cylinder, head, finfop))) {
  273.                 printf("\n...Format track FAILED\n");
  274.                 printf("  cyl %d  head %d\n", cylinder, head);
  275.                 return(1);
  276.             }
  277.             /*
  278.              * Read the whole track. No data verify; just rely on
  279.              * CRC.
  280.              */
  281.             if(fd_rw(live_fd,
  282.                 vfy_block,
  283.                 ssip->sects_per_trk,
  284.                 vfy_buf,
  285.                 TRUE,
  286.                 finfop))
  287.                 return(1);
  288.             vfy_block += ssip->sects_per_trk;
  289.         }
  290.         printf(".");   
  291.             fflush(stdout);
  292.     }
  293.     return(0);
  294. }
  295.  
  296. /*
  297.  * Format one track.
  298.  */
  299. int format_track(int fd, int cylinder, int head, struct fd_format_info *finfop)
  300. {
  301.     struct format_data *fdp_work;
  302.     int sector;
  303.     struct fd_ioreq ioreq;
  304.     struct fd_format_cmd *cmdp = (struct fd_format_cmd *)ioreq.cmd_blk;
  305.     int data_size;
  306.     int rtn=0;
  307.     struct fd_sectsize_info *ssip = &finfop->sectsize_info;
  308.  
  309.     data_size = sizeof(struct format_data) * ssip->sects_per_trk;
  310.  
  311.     /*
  312.      * Generate the data we'll DMA during the format track command.
  313.      * This consists if the headers for each sector on the cylinder.
  314.      */
  315.     fdp_work = fdp;
  316.     for(sector=1; sector<=ssip->sects_per_trk; sector++) {
  317.         fdp_work->cylinder = cylinder;
  318.         fdp_work->head = head;
  319.         fdp_work->sector = sector;
  320.         fdp_work->n = ssip->n;
  321.         fdp_work++;
  322.     }
  323.     if(seek_com(fd, cylinder * finfop->disk_info.tracks_per_cyl + head, 
  324.         finfop, finfop->density_info.density)) {
  325.         return(1);
  326.     }
  327.     usleep(20000);        /* head settling time - 20 ms (fixme) */
  328.     
  329.     /*
  330.      * Build a format command 
  331.      */
  332.     bzero(&ioreq, sizeof (struct fd_ioreq));
  333.     
  334.     ioreq.density = finfop->density_info.density;
  335.     ioreq.timeout = 5000;
  336.     ioreq.command = FDCMD_CMD_XFR;
  337.     ioreq.num_cmd_bytes = sizeof(struct fd_format_cmd);
  338.     ioreq.addrs = (caddr_t)fdp;
  339. #if    m68k
  340.     ioreq.byte_count = DMA_ENDALIGN(int, data_size);
  341. #else    m68k
  342.     ioreq.byte_count = data_size;
  343. #endif    m68k
  344.     ioreq.num_stat_bytes = SIZEOF_RW_STAT;
  345.     ioreq.flags = FD_IOF_DMA_WR;
  346.     
  347.     cmdp->mfm           = finfop->density_info.mfm;
  348.     cmdp->opcode        = FCCMD_FORMAT;
  349.     cmdp->hds           = head;
  350.     cmdp->n             = ssip->n;
  351.     cmdp->sects_per_trk = ssip->sects_per_trk;
  352.     cmdp->gap_length    = fmt_gap3_length;
  353.     cmdp->filler_data   = 0x5a;
  354.     rtn = do_ioc(fd, &ioreq);
  355.     if(rtn) {
  356.         printf("\n...Format (cylinder %d head %d) Failed\n", 
  357.             cylinder, head);
  358.     }
  359.     return(rtn);
  360. } /* format_track() */
  361.  
  362. int recalibrate(int fd, struct fd_format_info *fip) {
  363.     struct fd_ioreq ioreq;
  364.     struct fd_seek_cmd *cmdp = (struct fd_seek_cmd *)ioreq.cmd_blk;
  365.     int rtn=0;
  366.     
  367.     bzero(&ioreq, sizeof(struct fd_ioreq));
  368.     cmdp->opcode = FCCMD_RECAL;
  369.     ioreq.density = fip->density_info.density;
  370.     ioreq.timeout = 2000;
  371.     ioreq.command = FDCMD_CMD_XFR;
  372.     ioreq.num_cmd_bytes = sizeof(struct fd_recal_cmd);
  373.     ioreq.addrs = 0;
  374.     ioreq.byte_count = 0;
  375.     ioreq.num_stat_bytes = sizeof(struct fd_int_stat);
  376.     rtn = do_ioc(fd, &ioreq);
  377.     if(rtn) {
  378.         printf("\n...Recalibrate Failed\n");
  379.     }
  380.     return(rtn);
  381. }
  382.  
  383. int do_ioc(int fd, fd_ioreq_t fdiop)
  384. {    
  385.     int rtn=0;
  386.     
  387.     fdiop->status = FDR_SUCCESS;
  388.     if (ioctl(fd, FDIOCREQ, fdiop) < 0) {
  389.         perror("ioctl(FDIOCREQ)");
  390.         rtn = 1;
  391.         goto check_status;
  392.     }
  393.     if(fdiop->num_cmd_bytes != fdiop->cmd_bytes_xfr) {
  394.         printf("\n...Expected cmd byte count = 0x%x\n",
  395.              fdiop->num_cmd_bytes);
  396.         printf("   received cmd byte count = 0x%x\n",
  397.             fdiop->cmd_bytes_xfr);
  398.         rtn = 1;
  399.         goto check_status;
  400.     }
  401.     if(fdiop->num_stat_bytes != fdiop->stat_bytes_xfr) {
  402.         printf("\n...Expected status byte count = 0x%x\n", 
  403.             fdiop->num_stat_bytes);
  404.         printf("   received status byte count = 0x%x\n", 
  405.             fdiop->stat_bytes_xfr);
  406.         rtn = 1;
  407.         goto check_status;
  408.     }
  409.     if(fdiop->byte_count != fdiop->bytes_xfr) {
  410.         printf("\n...Expected byte count = 0x%x\n", fdiop->byte_count);
  411.         printf("   received byte count = 0x%x\n", fdiop->bytes_xfr);
  412.         rtn = 1;
  413.         goto check_status;
  414.     }
  415. check_status:
  416.     if(fdiop->status != FDR_SUCCESS) {
  417.         rtn = 1;
  418.         printf("\n...Unexpected status: %x\n", fdiop->status);
  419.     }
  420.     return(rtn);
  421. }
  422.  
  423. int seek_com(int fd, int track, struct fd_format_info *finfop, int density)
  424. {
  425.     struct fd_ioreq ioreq;
  426.     struct fd_seek_cmd *cmdp = (struct fd_seek_cmd *)ioreq.cmd_blk;
  427.     int rtn = 0;
  428.     
  429.     bzero(&ioreq, sizeof(struct fd_ioreq));
  430.     cmdp->opcode = FCCMD_SEEK;
  431.     cmdp->hds = track % finfop->disk_info.tracks_per_cyl;
  432.     cmdp->cyl = track / finfop->disk_info.tracks_per_cyl;
  433.     ioreq.timeout = 2000;
  434.     ioreq.density = density;
  435.     ioreq.command = FDCMD_CMD_XFR;
  436.     ioreq.num_cmd_bytes = SIZEOF_SEEK_CMD;
  437.     ioreq.num_stat_bytes = sizeof(struct fd_int_stat);
  438.     rtn = do_ioc(fd, &ioreq);
  439.     if(rtn) {
  440.         printf("\n...Seek (track %d) failed\n", track);
  441.     }
  442.     return(rtn);
  443. }
  444.  
  445. #define    USE_LIVE_IO    1
  446.  
  447. #if    USE_LIVE_IO
  448.  
  449. int fd_rw(int fd,
  450.     int block,
  451.     int block_count,
  452.     u_char *addrs,
  453.     boolean_t read_flag,
  454.     struct fd_format_info *finfop)
  455. {
  456.     int         rtn;
  457.     char         *read_str;
  458.     int         byte_count;
  459.     int        offset;
  460.         
  461.     read_str = read_flag ? "read " : "write";
  462.     offset = block * finfop->sectsize_info.sect_size;
  463.     byte_count = block_count * finfop->sectsize_info.sect_size;
  464.     rtn = lseek(fd, offset, L_SET);
  465.     if(rtn != offset) {
  466.         printf("Live Partition Seek Seek error on %s\n", read_str);
  467.         return(1);
  468.     }
  469.     if(read_flag) {
  470.         rtn = read(fd, addrs, byte_count);
  471.     }
  472.     else {
  473.         rtn = write(fd, addrs, byte_count);
  474.     }
  475.     if(rtn != byte_count) {
  476.         printf("\n");
  477.         if(rtn <= 0) {
  478.             perror(read_str);
  479.         }
  480.         else {
  481.             printf("Short %s (exp %d, recd %d)\n",
  482.                 read_str, byte_count, rtn);
  483.         }
  484.         printf("block %d block_count %d\n", block, block_count);
  485.         return(1);
  486.     }
  487.     return(0);
  488. } /* fd_rw() */
  489.  
  490.  
  491. #else    USE_LIVE_IO
  492.  
  493. int fd_rw(int fd,
  494.     int block,
  495.     int block_count,
  496.     u_char *addrs,
  497.     boolean_t read_flag,
  498.     struct fd_format_info *finfop)
  499. {
  500.     int rtn;
  501.     char *read_str;
  502.     int byte_count;
  503.     struct fd_rawio rawio;
  504.     
  505.     read_str = read_flag ? "read " : "write";
  506.         
  507.     rawio.sector = block;
  508.     rawio.sector_count = block_count;
  509.     rawio.dma_addrs = (caddr_t)addrs;
  510.     rawio.read = read_flag;
  511.     rawio.sects_xfr = rawio.status = -1;
  512.     
  513.     rtn = ioctl(fd, FDIOCRRW, &rawio);
  514.     if(rtn) {
  515.         if(read_flag)
  516.             perror("ioctl(FDIOCRW, read)");
  517.         else
  518.             perror("ioctl(FDIOCRW, write)");
  519.         return(1);
  520.             
  521.     }
  522.     if(rawio.status != FDR_SUCCESS) {
  523.         printf("\n...%s: rawio.status = %d(d)\n",
  524.             read_str, rawio.status);
  525.         return(1);
  526.     }
  527.     if(rawio.sects_xfr != block_count) {
  528.         printf("\n...ioctl(FDIOCRW, %s) moved %d(d) blocks, "
  529.             "expected %d(d) blocks\n", 
  530.             read_str, rawio.sects_xfr, block_count);
  531.         return(1);
  532.     }
  533.     return(0);
  534. } /* fd_rw() */
  535.  
  536. #endif    USE_LIVE_IO
  537.  
  538.  
  539.  
  540.  
  541.  
  542.