4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #pragma ident "%Z%%M% %I% %E% SMI"
32 * This file contains the format functions for floppy plug-in for
37 #include <sys/types.h>
38 #include <sys/dklabel.h>
45 #include <sys/param.h>
47 #include <sys/smedia.h>
48 #include "../../../library/inc/rmedia.h"
49 #include "f_defines.h"
55 extern void my_perror(char *err_string
);
59 static void restore_default_chars(int32_t fd
,
60 struct fd_char save_fdchar
,
61 struct dk_allmap save_allmap
);
63 format_floppy(int32_t fd
, void *ip
)
65 struct format_track
*ft
= (struct format_track
*)ip
;
67 int32_t transfer_rate
= 1000; /* transfer rate code */
68 int32_t sec_size
= 512; /* sector size */
69 uchar_t gap
= 0x54; /* format gap size */
73 int32_t chgd
; /* for testing disk changed/present */
75 int32_t size_of_part
, size_of_dev
;
76 int32_t spt
= 36; /* sectors per track */
78 uchar_t num_cyl
= 80; /* max number of cylinders */
79 struct fd_char save_fdchar
; /* original diskette characteristics */
80 struct dk_allmap save_allmap
; /* original diskette partition info */
81 int32_t D_flag
= 0; /* double (aka low) density flag */
82 int32_t E_flag
= 0; /* extended density */
83 int32_t H_flag
= 0; /* high density */
84 int32_t M_flag
= 0; /* medium density */
85 struct fd_char fdchar
;
86 struct dk_geom fdgeom
;
87 struct dk_allmap allmap
;
88 struct dk_cinfo dkinfo
;
89 int32_t start_head
, end_head
, start_cyl
, end_cyl
;
91 /* for verify buffers */
95 /* FDRAW ioctl command structures for seeking and formatting */
96 struct fd_raw fdr_seek
= {
97 FDRAW_SEEK
, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 struct fd_raw fdr_form
= {
105 0x4D, 0, 2, 0, 0x54, (char)0xA5, 0, 0, 0, 0,
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 format_flags
= ft
->flag
;
114 DPRINTF1("Format flag is %d\n", format_flags
);
115 if (format_flags
== SM_FORMAT_HD
) {
117 } else if (format_flags
== SM_FORMAT_DD
) {
119 } else if (format_flags
== SM_FORMAT_ED
) {
121 } else if (format_flags
== SM_FORMAT_MD
) {
124 DPRINTF("Invalid operation \n");
131 * restore drive to default geometry and characteristics
132 * (probably not implemented on sparc)
134 (void) ioctl(fd
, FDDEFGEOCHAR
, NULL
);
137 if (ioctl(fd
, DKIOCINFO
, &dkinfo
) < 0) {
138 PERROR("DKIOCINFO failed.");
143 /* get the default partititon maps */
144 if (ioctl(fd
, DKIOCGAPART
, &allmap
) < 0) {
145 PERROR("DKIOCGAPART failed.");
149 /* Save the original default partition maps */
150 save_allmap
= allmap
;
152 /* find out the characteristics of the default diskette */
153 if (ioctl(fd
, FDIOGCHAR
, &fdchar
) < 0) {
154 PERROR("FDIOGCHAR failed.");
158 /* Save the original characteristics of the default diskette */
159 save_fdchar
= fdchar
;
162 * The user may only format the entire diskette.
163 * formatting partion a or b is not allowed
165 size_of_part
= allmap
.dka_map
[dkinfo
.dki_partition
].dkl_nblk
167 size_of_dev
= fdchar
.fdc_ncyl
* fdchar
.fdc_nhead
168 * fdchar
.fdc_secptrack
* fdchar
.fdc_sec_size
;
170 if (size_of_part
!= size_of_dev
) {
171 DPRINTF("The entire diskette must be formatted\n");
172 DPRINTF1("size_of_part %d\n", size_of_part
);
173 DPRINTF1("size_of_dev %d\n", size_of_dev
);
178 /* find out the geometry of the drive */
179 if (ioctl(fd
, DKIOCGGEOM
, &fdgeom
) < 0) {
180 PERROR("DKIOCGGEOM failed.");
185 fdchar
.fdc_medium
= 3;
187 if (fdchar
.fdc_medium
== 5)
193 * set proper density flag in case we're formating to default
194 * characteristics because no density switch was input
198 if ((E_flag
| H_flag
| D_flag
| M_flag
) == 0) {
199 switch (fdchar
.fdc_transfer_rate
) {
201 /* assumes only ED uses 1.0 MB/sec */
207 * default to HD even though High density and
208 * "medium" density both use 500 KB/sec
214 /* assumes only DD uses 250 KB/sec */
225 if (drive_size
== 5) {
233 if (drive_size
== 5) {
234 if (fdchar
.fdc_transfer_rate
== 500) {
236 * formatting a 360KB DD diskette in
237 * a 1.2MB drive is not a good idea
240 fdchar
.fdc_steps
= 2;
255 * 416.67 KB/sec is the effective transfer rate of a "medium"
256 * density diskette spun at 300 rpm instead of 360 rpm
265 transfer_rate
= 1000;
273 * Medium density diskettes have 1024 byte blocks. The dk_map
274 * structure in dklabel.h assumes the blocks size is DEVBSIZE (512)
275 * bytes. The dkl_nblk field is in terms of DEVBSIZE byte blocks
276 * while the spt variable is in terms of the true block size on
279 if (allmap
.dka_map
[2].dkl_nblk
!=
280 (2 * num_cyl
* spt
* (M_flag
? 2 : 1))) {
281 allmap
.dka_map
[1].dkl_cylno
= num_cyl
- 1;
282 allmap
.dka_map
[0].dkl_nblk
= 2 * (num_cyl
- 1) * spt
*
284 allmap
.dka_map
[1].dkl_nblk
= 2 * spt
* (M_flag
? 2 : 1);
285 allmap
.dka_map
[2].dkl_nblk
= 2 * num_cyl
* spt
*
287 if (allmap
.dka_map
[3].dkl_nblk
)
288 allmap
.dka_map
[3].dkl_nblk
= 2 * (num_cyl
- 1) * spt
*
290 if (allmap
.dka_map
[4].dkl_nblk
)
291 allmap
.dka_map
[4].dkl_nblk
=
292 2 * spt
* (M_flag
? 2 : 1);
298 if (num_cyl
> fdchar
.fdc_ncyl
|| spt
> fdchar
.fdc_secptrack
||
299 transfer_rate
> fdchar
.fdc_transfer_rate
) {
300 PERROR("drive not capable of requested density");
304 if (num_cyl
!= fdchar
.fdc_ncyl
|| spt
!= fdchar
.fdc_secptrack
||
305 transfer_rate
!= fdchar
.fdc_transfer_rate
) {
308 * The SPARC fd driver is using a non-zero value in
309 * fdc_medium to indicate the 360 rpm, 77 track,
310 * 9 sectors/track, 1024 bytes/sector mode of operation
311 * (similar to an 8", DS/DD, 1.2 MB floppy).
313 * The x86 fd driver uses fdc_medium as the diameter
314 * indicator, either 3 or 5. It should not be modified.
317 fdchar
.fdc_medium
= M_flag
? 1 : 0;
319 fdchar
.fdc_transfer_rate
= transfer_rate
;
320 fdchar
.fdc_ncyl
= num_cyl
;
321 fdchar
.fdc_sec_size
= sec_size
;
322 fdchar
.fdc_secptrack
= spt
;
324 if (ioctl(fd
, FDIOSCHAR
, &fdchar
) < 0) {
325 PERROR("FDIOSCHAR (density selection) failed");
326 /* restore the default characteristics */
327 restore_default_chars(fd
, save_fdchar
, save_allmap
);
330 if (ioctl(fd
, DKIOCSAPART
, &allmap
) < 0) {
331 PERROR("DKIOCSAPART failed");
333 /* restore the default characteristics */
334 restore_default_chars(fd
, save_fdchar
, save_allmap
);
339 cyl_size
= 2 * sec_size
* spt
;
341 if ((obuf
= (uchar_t
*)malloc((size_t)cyl_size
)) == 0) {
342 PERROR("car't malloc verify buffer");
343 /* restore the default characteristics */
344 restore_default_chars(fd
, save_fdchar
, save_allmap
);
348 * for those systems that support this ioctl, they will
349 * return whether or not a diskette is in the drive.
351 if (ioctl(fd
, FDGETCHANGE
, &chgd
) == 0) {
352 if (chgd
& FDGC_CURRENT
) {
353 (void) fprintf(stderr
,
354 gettext("no diskette in drive \n"));
356 /* restore the default characteristics */
357 restore_default_chars(fd
, save_fdchar
, save_allmap
);
360 if (chgd
& FDGC_CURWPROT
) {
361 (void) fprintf(stderr
,
362 gettext("Media is write protected\n"));
364 /* restore the default characteristics */
365 restore_default_chars(fd
, save_fdchar
, save_allmap
);
370 if ((fbuf
= (uchar_t
*)malloc((unsigned)(4 * spt
))) == 0) {
371 PERROR("Could not malloc format header buffer");
372 restore_default_chars(fd
, save_fdchar
, save_allmap
);
376 * do the format, a track at a time
378 if (ft
->track_no
== -1) {
382 end_head
= fdchar
.fdc_nhead
;
384 start_cyl
= ft
->track_no
;
385 end_cyl
= ft
->track_no
+ 1;
386 start_head
= ft
->head
;
387 end_head
= ft
->head
+ 1;
388 if ((end_cyl
> num_cyl
) || (end_head
> fdchar
.fdc_nhead
)) {
394 for (cyl
= start_cyl
; cyl
< (int32_t)end_cyl
; cyl
++) {
396 * This is not the optimal ioctl to format the floppy.
397 * The device driver should do do the work,
398 * instead of this program mucking with a lot
399 * of low-level, device-dependent code.
401 fdr_seek
.fdr_cmd
[2] = cyl
;
402 if (ioctl(fd
, FDRAW
, &fdr_seek
) < 0) {
403 (void) fprintf(stderr
,
404 gettext(" seek to cyl %d failed\n"),
407 /* restore the default characteristics */
408 restore_default_chars(fd
, save_fdchar
, save_allmap
);
412 * Assume that the fd driver has issued a SENSE_INT
413 * command to complete the seek operation.
416 for (hd
= start_head
; hd
< end_head
; hd
++) {
418 for (i
= 1; i
<= spt
; i
++) {
421 *p
++ = (uchar_t
)i
; /* sector # */
422 *p
++ = (sec_size
== 1024) ? 3 : 2;
425 * ASSUME the fd driver is going to set drive-select
426 * bits in the second command byte
428 fdr_form
.fdr_cmd
[1] = hd
<< 2;
429 fdr_form
.fdr_cmd
[2] = (sec_size
== 1024) ? 3 : 2;
430 fdr_form
.fdr_cmd
[3] = spt
;
431 fdr_form
.fdr_cmd
[4] = gap
;
432 fdr_form
.fdr_nbytes
= 4 * spt
;
433 fdr_form
.fdr_addr
= (char *)fbuf
;
435 if (ioctl(fd
, FDRAW
, &fdr_form
) < 0) {
438 (void) fprintf(stderr
,
440 "format of cyl %d head %d failed\n"),
443 /* restore the default characteristics */
444 restore_default_chars(fd
, save_fdchar
,
448 if (fdr_form
.fdr_result
[0] & 0xC0) {
449 if (fdr_form
.fdr_result
[1] & 0x02) {
450 (void) fprintf(stderr
, gettext(
452 "diskette is write protected\n"));
455 * restore the default
458 restore_default_chars(fd
, save_fdchar
,
462 (void) fprintf(stderr
,
464 "format of cyl %d head %d failed\n"),
467 /* restore the default characteristics */
468 restore_default_chars(fd
, save_fdchar
,
478 if (llseek(fd
, cyl
* cyl_size
, 0) != cyl
* cyl_size
) {
479 PERROR(" bad seek to format verify, ");
480 /* restore the default characteristics */
481 restore_default_chars(fd
, save_fdchar
,
485 if (fdchar
.fdc_nhead
== end_head
) {
486 if (read(fd
, obuf
, cyl_size
) != cyl_size
) {
487 PERROR("Could not read format data");
488 /* restore the default characteristics */
489 restore_default_chars(fd
, save_fdchar
,
495 if (llseek(fd
, (off_t
)0, 0) != 0) {
496 PERROR("seek to blk 0 failed");
497 /* restore the default characteristics */
498 restore_default_chars(fd
, save_fdchar
, save_allmap
);
506 * Restore the default characteristics of the floppy diskette.
507 * Fdformat changes the characteristics in the process of formatting.
508 * If fdformat fails while in the process of doing the format, fdformat
509 * should clean up after itself and reset the driver back to the original
514 restore_default_chars(int32_t fd
,
515 struct fd_char save_fdchar
,
516 struct dk_allmap save_allmap
)
521 * When this function is called, fdformat is failing anyways,
522 * so the errors are not processed.
525 (void) ioctl(fd
, FDIOSCHAR
, &save_fdchar
);
527 (void) ioctl(fd
, DKIOCSAPART
, &save_allmap
);
530 * Before looking at the diskette's characteristics, format_floppy()
531 * sets the x86 floppy driver to the default characteristics.
532 * restore drive to default geometry and
533 * characteristics. This ioctl isn't implemented on
536 (void) ioctl(fd
, FDDEFGEOCHAR
, NULL
);
541 _m_media_format(rmedia_handle_t
*handle
, void *ip
) {
542 struct format_track ft
;
544 /* Check for valid handle */
545 if (handle
== NULL
) {
546 DPRINTF("Null Handle\n");
550 if (handle
->sm_signature
!= (int32_t)LIBSMEDIA_SIGNATURE
) {
551 DPRINTF("Invalid signature in handle.\n");
553 "Signature expected=0x%x, found=0x%x\n",
554 LIBSMEDIA_SIGNATURE
, handle
->sm_signature
);
558 if (handle
->sm_fd
< 0) {
559 DPRINTF("Invalid file handle.\n");
563 DPRINTF("Format floppy called \n");
566 ft
.flag
= ((struct format_flags
*)ip
)->flavor
;
567 return (format_floppy(handle
->sm_fd
, &ft
));
572 _m_media_format_track(rmedia_handle_t
*handle
, void *ip
)
575 /* Check for valid handle */
576 if (handle
== NULL
) {
577 DPRINTF("Null Handle\n");
581 if (handle
->sm_signature
!= (int32_t)LIBSMEDIA_SIGNATURE
) {
582 DPRINTF("Invalid signature in handle.\n");
584 "Signature expected=0x%x, found=0x%x\n",
585 LIBSMEDIA_SIGNATURE
, handle
->sm_signature
);
589 if (handle
->sm_fd
< 0) {
590 DPRINTF("Invalid file handle.\n");
596 struct format_track
*ft
= (struct format_track
*)ip
;
597 DPRINTF2("Format track %d head %d\n", ft
->track_no
, ft
->head
);
600 return (format_floppy(handle
->sm_fd
, ip
));