Annotation of Examples/UNIX/Floppy/fdform.c, revision 1.1.1.1

1.1       root        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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.