|
|
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.