home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.0 / NeXTSTEP3.0.iso / NextDeveloper / Examples / UNIX / Floppy / fdform.c next >
Encoding:
Text File  |  1992-07-24  |  10.8 KB  |  462 lines

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