|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.