1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate 
23*7c478bd9Sstevel@tonic-gate /*
24*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
25*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
26*7c478bd9Sstevel@tonic-gate  */
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate /*
29*7c478bd9Sstevel@tonic-gate  * f_format.c :
30*7c478bd9Sstevel@tonic-gate  *      This file contains the format functions for floppy plug-in for
31*7c478bd9Sstevel@tonic-gate  * 	library libsm.so.
32*7c478bd9Sstevel@tonic-gate  */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <stdio.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/dklabel.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/fdio.h>
39*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
40*7c478bd9Sstevel@tonic-gate #include <unistd.h>
41*7c478bd9Sstevel@tonic-gate #include <locale.h>
42*7c478bd9Sstevel@tonic-gate #include <errno.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
44*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/smedia.h>
46*7c478bd9Sstevel@tonic-gate #include "../../../library/inc/rmedia.h"
47*7c478bd9Sstevel@tonic-gate #include "f_defines.h"
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate /*
50*7c478bd9Sstevel@tonic-gate  * extern functions
51*7c478bd9Sstevel@tonic-gate  */
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate extern void my_perror(char *err_string);
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate  * local functions
56*7c478bd9Sstevel@tonic-gate  */
57*7c478bd9Sstevel@tonic-gate static void	restore_default_chars(int32_t fd,
58*7c478bd9Sstevel@tonic-gate 				    struct fd_char save_fdchar,
59*7c478bd9Sstevel@tonic-gate 				    struct dk_allmap save_allmap);
60*7c478bd9Sstevel@tonic-gate static int32_t
format_floppy(int32_t fd,void * ip)61*7c478bd9Sstevel@tonic-gate format_floppy(int32_t fd, void *ip)
62*7c478bd9Sstevel@tonic-gate {
63*7c478bd9Sstevel@tonic-gate 	struct	format_track *ft = (struct format_track *)ip;
64*7c478bd9Sstevel@tonic-gate 	int32_t format_flags;
65*7c478bd9Sstevel@tonic-gate 	int32_t	transfer_rate = 1000;   /* transfer rate code */
66*7c478bd9Sstevel@tonic-gate 	int32_t	sec_size = 512;		/* sector size */
67*7c478bd9Sstevel@tonic-gate 	uchar_t	gap = 0x54;		/* format gap size */
68*7c478bd9Sstevel@tonic-gate 	uchar_t  *fbuf, *p;
69*7c478bd9Sstevel@tonic-gate 	int32_t	cyl_size;
70*7c478bd9Sstevel@tonic-gate 	int32_t	i;
71*7c478bd9Sstevel@tonic-gate 	int32_t	chgd;			/* for testing disk changed/present */
72*7c478bd9Sstevel@tonic-gate 	int32_t	cyl, hd;
73*7c478bd9Sstevel@tonic-gate 	int32_t	size_of_part, size_of_dev;
74*7c478bd9Sstevel@tonic-gate 	int32_t	spt = 36;		/* sectors per track */
75*7c478bd9Sstevel@tonic-gate 	int32_t	drive_size;
76*7c478bd9Sstevel@tonic-gate 	uchar_t	num_cyl = 80;		/*  max number of cylinders */
77*7c478bd9Sstevel@tonic-gate 	struct fd_char save_fdchar;	/* original diskette characteristics */
78*7c478bd9Sstevel@tonic-gate 	struct dk_allmap save_allmap;	/* original diskette partition info */
79*7c478bd9Sstevel@tonic-gate 	int32_t	D_flag = 0;	/* double (aka low) density flag */
80*7c478bd9Sstevel@tonic-gate 	int32_t	E_flag = 0;	/* extended density */
81*7c478bd9Sstevel@tonic-gate 	int32_t	H_flag = 0;	/* high density */
82*7c478bd9Sstevel@tonic-gate 	int32_t	M_flag = 0;	/* medium density */
83*7c478bd9Sstevel@tonic-gate 	struct fd_char 		fdchar;
84*7c478bd9Sstevel@tonic-gate 	struct dk_geom 		fdgeom;
85*7c478bd9Sstevel@tonic-gate 	struct dk_allmap 	allmap;
86*7c478bd9Sstevel@tonic-gate 	struct dk_cinfo 	dkinfo;
87*7c478bd9Sstevel@tonic-gate 	int32_t start_head, end_head, start_cyl, end_cyl;
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate 	/* for verify buffers */
90*7c478bd9Sstevel@tonic-gate 	static uchar_t	*obuf;
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 	/* FDRAW ioctl command structures for seeking and formatting */
94*7c478bd9Sstevel@tonic-gate 	struct fd_raw fdr_seek = {
95*7c478bd9Sstevel@tonic-gate 		FDRAW_SEEK, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96*7c478bd9Sstevel@tonic-gate 		3,
97*7c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98*7c478bd9Sstevel@tonic-gate 		0,
99*7c478bd9Sstevel@tonic-gate 		0
100*7c478bd9Sstevel@tonic-gate 	};
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate 	struct fd_raw fdr_form = {
103*7c478bd9Sstevel@tonic-gate 		0x4D, 0, 2, 0, 0x54, (char)0xA5, 0, 0, 0, 0,
104*7c478bd9Sstevel@tonic-gate 		6,
105*7c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106*7c478bd9Sstevel@tonic-gate 		0,	/* nbytes */
107*7c478bd9Sstevel@tonic-gate 		0	/* addr */
108*7c478bd9Sstevel@tonic-gate 	};
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate 	format_flags = ft->flag;
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	DPRINTF1("Format flag is %d\n", format_flags);
113*7c478bd9Sstevel@tonic-gate 	if (format_flags == SM_FORMAT_HD) {
114*7c478bd9Sstevel@tonic-gate 		H_flag = 1;
115*7c478bd9Sstevel@tonic-gate 	} else if (format_flags == SM_FORMAT_DD) {
116*7c478bd9Sstevel@tonic-gate 		D_flag = 1;
117*7c478bd9Sstevel@tonic-gate 	} else if (format_flags == SM_FORMAT_ED) {
118*7c478bd9Sstevel@tonic-gate 		E_flag = 1;
119*7c478bd9Sstevel@tonic-gate 	} else if (format_flags == SM_FORMAT_MD) {
120*7c478bd9Sstevel@tonic-gate 		M_flag = 1;
121*7c478bd9Sstevel@tonic-gate 	} else {
122*7c478bd9Sstevel@tonic-gate 		DPRINTF("Invalid operation \n");
123*7c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
124*7c478bd9Sstevel@tonic-gate 		return (-1);
125*7c478bd9Sstevel@tonic-gate 	}
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	/*
129*7c478bd9Sstevel@tonic-gate 	 * restore drive to default geometry and characteristics
130*7c478bd9Sstevel@tonic-gate 	 * (probably not implemented on sparc)
131*7c478bd9Sstevel@tonic-gate 	 */
132*7c478bd9Sstevel@tonic-gate 	(void) ioctl(fd, FDDEFGEOCHAR, NULL);
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &dkinfo) < 0) {
136*7c478bd9Sstevel@tonic-gate 		PERROR("DKIOCINFO failed.");
137*7c478bd9Sstevel@tonic-gate 		exit(3);
138*7c478bd9Sstevel@tonic-gate 	}
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	/* get the default partititon maps */
142*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCGAPART, &allmap) < 0) {
143*7c478bd9Sstevel@tonic-gate 		PERROR("DKIOCGAPART failed.");
144*7c478bd9Sstevel@tonic-gate 		return (-1);
145*7c478bd9Sstevel@tonic-gate 	}
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	/* Save the original default partition maps */
148*7c478bd9Sstevel@tonic-gate 	save_allmap = allmap;
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	/* find out the characteristics of the default diskette */
151*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, FDIOGCHAR, &fdchar) < 0) {
152*7c478bd9Sstevel@tonic-gate 		PERROR("FDIOGCHAR failed.");
153*7c478bd9Sstevel@tonic-gate 		return (-1);
154*7c478bd9Sstevel@tonic-gate 	}
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 	/* Save the original characteristics of the default diskette */
157*7c478bd9Sstevel@tonic-gate 	save_fdchar = fdchar;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	/*
160*7c478bd9Sstevel@tonic-gate 	 * The user may only format the entire diskette.
161*7c478bd9Sstevel@tonic-gate 	 * formatting partion a or b is not allowed
162*7c478bd9Sstevel@tonic-gate 	 */
163*7c478bd9Sstevel@tonic-gate 	size_of_part = allmap.dka_map[dkinfo.dki_partition].dkl_nblk
164*7c478bd9Sstevel@tonic-gate 			* DEV_BSIZE;
165*7c478bd9Sstevel@tonic-gate 	size_of_dev = fdchar.fdc_ncyl * fdchar.fdc_nhead
166*7c478bd9Sstevel@tonic-gate 			* fdchar.fdc_secptrack * fdchar.fdc_sec_size;
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	if (size_of_part != size_of_dev) {
169*7c478bd9Sstevel@tonic-gate 		DPRINTF("The entire diskette must be formatted\n");
170*7c478bd9Sstevel@tonic-gate 		DPRINTF1("size_of_part %d\n", size_of_part);
171*7c478bd9Sstevel@tonic-gate 		DPRINTF1("size_of_dev %d\n", size_of_dev);
172*7c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
173*7c478bd9Sstevel@tonic-gate 		return (-1);
174*7c478bd9Sstevel@tonic-gate 	}
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	/* find out the geometry of the drive */
177*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCGGEOM, &fdgeom) < 0) {
178*7c478bd9Sstevel@tonic-gate 		PERROR("DKIOCGGEOM failed.");
179*7c478bd9Sstevel@tonic-gate 		return (-1);
180*7c478bd9Sstevel@tonic-gate 	}
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate #ifdef sparc
183*7c478bd9Sstevel@tonic-gate 	fdchar.fdc_medium = 3;
184*7c478bd9Sstevel@tonic-gate #endif
185*7c478bd9Sstevel@tonic-gate 	if (fdchar.fdc_medium == 5)
186*7c478bd9Sstevel@tonic-gate 		drive_size = 5;
187*7c478bd9Sstevel@tonic-gate 	else
188*7c478bd9Sstevel@tonic-gate 		drive_size = 3;
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	/*
191*7c478bd9Sstevel@tonic-gate 	 * set proper density flag in case we're formating to default
192*7c478bd9Sstevel@tonic-gate 	 * characteristics because no density switch was input
193*7c478bd9Sstevel@tonic-gate 	 */
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate /* XXX */
196*7c478bd9Sstevel@tonic-gate 	if ((E_flag | H_flag | D_flag | M_flag) == 0) {
197*7c478bd9Sstevel@tonic-gate 		switch (fdchar.fdc_transfer_rate) {
198*7c478bd9Sstevel@tonic-gate 		case 1000:
199*7c478bd9Sstevel@tonic-gate 			/* assumes only ED uses 1.0 MB/sec */
200*7c478bd9Sstevel@tonic-gate 			E_flag++;
201*7c478bd9Sstevel@tonic-gate 			break;
202*7c478bd9Sstevel@tonic-gate 		case 500:
203*7c478bd9Sstevel@tonic-gate 		default:
204*7c478bd9Sstevel@tonic-gate 			/*
205*7c478bd9Sstevel@tonic-gate 			 * default to HD even though High density and
206*7c478bd9Sstevel@tonic-gate 			 * "medium" density both use 500 KB/sec
207*7c478bd9Sstevel@tonic-gate 			 */
208*7c478bd9Sstevel@tonic-gate 			H_flag++;
209*7c478bd9Sstevel@tonic-gate 			break;
210*7c478bd9Sstevel@tonic-gate #ifndef sparc
211*7c478bd9Sstevel@tonic-gate 		case 250:
212*7c478bd9Sstevel@tonic-gate 			/* assumes only DD uses 250 KB/sec */
213*7c478bd9Sstevel@tonic-gate 			D_flag++;
214*7c478bd9Sstevel@tonic-gate 			break;
215*7c478bd9Sstevel@tonic-gate #endif
216*7c478bd9Sstevel@tonic-gate 		}
217*7c478bd9Sstevel@tonic-gate 	}
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	if (H_flag) {
220*7c478bd9Sstevel@tonic-gate 		transfer_rate = 500;
221*7c478bd9Sstevel@tonic-gate 		num_cyl = 80;
222*7c478bd9Sstevel@tonic-gate 		sec_size = 512;
223*7c478bd9Sstevel@tonic-gate 		if (drive_size == 5) {
224*7c478bd9Sstevel@tonic-gate 			spt = 15;
225*7c478bd9Sstevel@tonic-gate 		} else {
226*7c478bd9Sstevel@tonic-gate 			spt = 18;
227*7c478bd9Sstevel@tonic-gate 		}
228*7c478bd9Sstevel@tonic-gate 		gap = 0x54;
229*7c478bd9Sstevel@tonic-gate 	} else if (D_flag) {
230*7c478bd9Sstevel@tonic-gate 		transfer_rate = 250;
231*7c478bd9Sstevel@tonic-gate 		if (drive_size == 5) {
232*7c478bd9Sstevel@tonic-gate 			if (fdchar.fdc_transfer_rate == 500) {
233*7c478bd9Sstevel@tonic-gate 				/*
234*7c478bd9Sstevel@tonic-gate 				 * formatting a 360KB DD diskette in
235*7c478bd9Sstevel@tonic-gate 				 * a 1.2MB drive is not a good idea
236*7c478bd9Sstevel@tonic-gate 				 */
237*7c478bd9Sstevel@tonic-gate 				transfer_rate = 300;
238*7c478bd9Sstevel@tonic-gate 				fdchar.fdc_steps = 2;
239*7c478bd9Sstevel@tonic-gate 			}
240*7c478bd9Sstevel@tonic-gate 			num_cyl = 40;
241*7c478bd9Sstevel@tonic-gate 			gap = 0x50;
242*7c478bd9Sstevel@tonic-gate 		} else {
243*7c478bd9Sstevel@tonic-gate 			num_cyl = 80;
244*7c478bd9Sstevel@tonic-gate 			gap = 0x54;
245*7c478bd9Sstevel@tonic-gate 		}
246*7c478bd9Sstevel@tonic-gate 		sec_size = 512;
247*7c478bd9Sstevel@tonic-gate 		spt = 9;
248*7c478bd9Sstevel@tonic-gate 	} else if (M_flag) {
249*7c478bd9Sstevel@tonic-gate #ifdef sparc
250*7c478bd9Sstevel@tonic-gate 		transfer_rate = 500;
251*7c478bd9Sstevel@tonic-gate #else
252*7c478bd9Sstevel@tonic-gate 		/*
253*7c478bd9Sstevel@tonic-gate 		 * 416.67 KB/sec is the effective transfer rate of a "medium"
254*7c478bd9Sstevel@tonic-gate 		 * density diskette spun at 300 rpm instead of 360 rpm
255*7c478bd9Sstevel@tonic-gate 		 */
256*7c478bd9Sstevel@tonic-gate 		transfer_rate = 417;
257*7c478bd9Sstevel@tonic-gate #endif
258*7c478bd9Sstevel@tonic-gate 		num_cyl = 77;
259*7c478bd9Sstevel@tonic-gate 		sec_size = 1024;
260*7c478bd9Sstevel@tonic-gate 		spt = 8;
261*7c478bd9Sstevel@tonic-gate 		gap = 0x74;
262*7c478bd9Sstevel@tonic-gate 	} else if (E_flag) {
263*7c478bd9Sstevel@tonic-gate 		transfer_rate = 1000;
264*7c478bd9Sstevel@tonic-gate 		num_cyl = 80;
265*7c478bd9Sstevel@tonic-gate 		sec_size = 512;
266*7c478bd9Sstevel@tonic-gate 		spt = 36;
267*7c478bd9Sstevel@tonic-gate 		gap = 0x54;
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 	/*
271*7c478bd9Sstevel@tonic-gate 	 * Medium density diskettes have 1024 byte blocks.  The dk_map
272*7c478bd9Sstevel@tonic-gate 	 * structure in dklabel.h assumes the blocks size is DEVBSIZE (512)
273*7c478bd9Sstevel@tonic-gate 	 * bytes.  The dkl_nblk field is in terms of DEVBSIZE byte blocks
274*7c478bd9Sstevel@tonic-gate 	 * while the spt variable is in terms of the true block size on
275*7c478bd9Sstevel@tonic-gate 	 * the diskette.
276*7c478bd9Sstevel@tonic-gate 	 */
277*7c478bd9Sstevel@tonic-gate 	if (allmap.dka_map[2].dkl_nblk !=
278*7c478bd9Sstevel@tonic-gate 		(2 * num_cyl * spt * (M_flag ? 2 : 1))) {
279*7c478bd9Sstevel@tonic-gate 		allmap.dka_map[1].dkl_cylno = num_cyl - 1;
280*7c478bd9Sstevel@tonic-gate 		allmap.dka_map[0].dkl_nblk = 2 * (num_cyl - 1) * spt *
281*7c478bd9Sstevel@tonic-gate 			(M_flag ? 2 : 1);
282*7c478bd9Sstevel@tonic-gate 		allmap.dka_map[1].dkl_nblk = 2 * spt * (M_flag ? 2 : 1);
283*7c478bd9Sstevel@tonic-gate 		allmap.dka_map[2].dkl_nblk = 2 * num_cyl * spt *
284*7c478bd9Sstevel@tonic-gate 			(M_flag ? 2 : 1);
285*7c478bd9Sstevel@tonic-gate 		if (allmap.dka_map[3].dkl_nblk)
286*7c478bd9Sstevel@tonic-gate 			allmap.dka_map[3].dkl_nblk = 2 * (num_cyl - 1) * spt *
287*7c478bd9Sstevel@tonic-gate 				(M_flag ? 2 : 1);
288*7c478bd9Sstevel@tonic-gate 		if (allmap.dka_map[4].dkl_nblk)
289*7c478bd9Sstevel@tonic-gate 			allmap.dka_map[4].dkl_nblk =
290*7c478bd9Sstevel@tonic-gate 				2 * spt * (M_flag ? 2 : 1);
291*7c478bd9Sstevel@tonic-gate 	}
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate #ifndef sparc
296*7c478bd9Sstevel@tonic-gate 	if (num_cyl > fdchar.fdc_ncyl || spt > fdchar.fdc_secptrack ||
297*7c478bd9Sstevel@tonic-gate 	    transfer_rate > fdchar.fdc_transfer_rate) {
298*7c478bd9Sstevel@tonic-gate 		PERROR("drive not capable of requested density");
299*7c478bd9Sstevel@tonic-gate 		return (-1);
300*7c478bd9Sstevel@tonic-gate 	}
301*7c478bd9Sstevel@tonic-gate #endif
302*7c478bd9Sstevel@tonic-gate 	if (num_cyl != fdchar.fdc_ncyl || spt != fdchar.fdc_secptrack ||
303*7c478bd9Sstevel@tonic-gate 	    transfer_rate != fdchar.fdc_transfer_rate) {
304*7c478bd9Sstevel@tonic-gate 		/*
305*7c478bd9Sstevel@tonic-gate 		 * -- CAUTION --
306*7c478bd9Sstevel@tonic-gate 		 * The SPARC fd driver is using a non-zero value in
307*7c478bd9Sstevel@tonic-gate 		 * fdc_medium to indicate the 360 rpm, 77 track,
308*7c478bd9Sstevel@tonic-gate 		 * 9 sectors/track, 1024 bytes/sector mode of operation
309*7c478bd9Sstevel@tonic-gate 		 * (similar to an 8", DS/DD, 1.2 MB floppy).
310*7c478bd9Sstevel@tonic-gate 		 *
311*7c478bd9Sstevel@tonic-gate 		 * The x86 fd driver uses fdc_medium as the diameter
312*7c478bd9Sstevel@tonic-gate 		 * indicator, either 3 or 5.  It should not be modified.
313*7c478bd9Sstevel@tonic-gate 		 */
314*7c478bd9Sstevel@tonic-gate #ifdef sparc
315*7c478bd9Sstevel@tonic-gate 		fdchar.fdc_medium = M_flag ? 1 : 0;
316*7c478bd9Sstevel@tonic-gate #endif
317*7c478bd9Sstevel@tonic-gate 		fdchar.fdc_transfer_rate = transfer_rate;
318*7c478bd9Sstevel@tonic-gate 		fdchar.fdc_ncyl = num_cyl;
319*7c478bd9Sstevel@tonic-gate 		fdchar.fdc_sec_size = sec_size;
320*7c478bd9Sstevel@tonic-gate 		fdchar.fdc_secptrack = spt;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, FDIOSCHAR, &fdchar) < 0) {
323*7c478bd9Sstevel@tonic-gate 			PERROR("FDIOSCHAR (density selection) failed");
324*7c478bd9Sstevel@tonic-gate 			/* restore the default characteristics */
325*7c478bd9Sstevel@tonic-gate 			restore_default_chars(fd, save_fdchar, save_allmap);
326*7c478bd9Sstevel@tonic-gate 			return (-1);
327*7c478bd9Sstevel@tonic-gate 		}
328*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, DKIOCSAPART, &allmap) < 0) {
329*7c478bd9Sstevel@tonic-gate 			PERROR("DKIOCSAPART failed");
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 			/* restore the default characteristics */
332*7c478bd9Sstevel@tonic-gate 			restore_default_chars(fd, save_fdchar, save_allmap);
333*7c478bd9Sstevel@tonic-gate 				return (-1);
334*7c478bd9Sstevel@tonic-gate 		}
335*7c478bd9Sstevel@tonic-gate 	}
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	cyl_size = 2 * sec_size * spt;
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	if ((obuf = (uchar_t *)malloc((size_t)cyl_size)) == 0) {
340*7c478bd9Sstevel@tonic-gate 		PERROR("car't malloc verify buffer");
341*7c478bd9Sstevel@tonic-gate 		/* restore the default characteristics */
342*7c478bd9Sstevel@tonic-gate 		restore_default_chars(fd, save_fdchar, save_allmap);
343*7c478bd9Sstevel@tonic-gate 		return (-1);
344*7c478bd9Sstevel@tonic-gate 	}
345*7c478bd9Sstevel@tonic-gate 	/*
346*7c478bd9Sstevel@tonic-gate 	 * for those systems that support this ioctl, they will
347*7c478bd9Sstevel@tonic-gate 	 * return whether or not a diskette is in the drive.
348*7c478bd9Sstevel@tonic-gate 	 */
349*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, FDGETCHANGE, &chgd) == 0) {
350*7c478bd9Sstevel@tonic-gate 		if (chgd & FDGC_CURRENT) {
351*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
352*7c478bd9Sstevel@tonic-gate 			    gettext("no diskette in drive \n"));
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 			/* restore the default characteristics */
355*7c478bd9Sstevel@tonic-gate 			restore_default_chars(fd, save_fdchar, save_allmap);
356*7c478bd9Sstevel@tonic-gate 			return (-1);
357*7c478bd9Sstevel@tonic-gate 		}
358*7c478bd9Sstevel@tonic-gate 		if (chgd & FDGC_CURWPROT) {
359*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
360*7c478bd9Sstevel@tonic-gate 			    gettext("Media is write protected\n"));
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 			/* restore the default characteristics */
363*7c478bd9Sstevel@tonic-gate 			restore_default_chars(fd, save_fdchar, save_allmap);
364*7c478bd9Sstevel@tonic-gate 			return (-1);
365*7c478bd9Sstevel@tonic-gate 		}
366*7c478bd9Sstevel@tonic-gate 	}
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	if ((fbuf = (uchar_t *)malloc((unsigned)(4 * spt))) == 0) {
369*7c478bd9Sstevel@tonic-gate 		PERROR("Could not malloc format header buffer");
370*7c478bd9Sstevel@tonic-gate 		restore_default_chars(fd, save_fdchar, save_allmap);
371*7c478bd9Sstevel@tonic-gate 		return (-1);
372*7c478bd9Sstevel@tonic-gate 	}
373*7c478bd9Sstevel@tonic-gate 	/*
374*7c478bd9Sstevel@tonic-gate 	 * do the format, a track at a time
375*7c478bd9Sstevel@tonic-gate 	 */
376*7c478bd9Sstevel@tonic-gate 	if (ft->track_no == -1) {
377*7c478bd9Sstevel@tonic-gate 		start_cyl = 0;
378*7c478bd9Sstevel@tonic-gate 		end_cyl	  = num_cyl;
379*7c478bd9Sstevel@tonic-gate 		start_head =  0;
380*7c478bd9Sstevel@tonic-gate 		end_head = fdchar.fdc_nhead;
381*7c478bd9Sstevel@tonic-gate 	} else {
382*7c478bd9Sstevel@tonic-gate 		start_cyl = ft->track_no;
383*7c478bd9Sstevel@tonic-gate 		end_cyl = ft->track_no + 1;
384*7c478bd9Sstevel@tonic-gate 		start_head = ft->head;
385*7c478bd9Sstevel@tonic-gate 		end_head = ft->head + 1;
386*7c478bd9Sstevel@tonic-gate 		if ((end_cyl > num_cyl) || (end_head > fdchar.fdc_nhead)) {
387*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
388*7c478bd9Sstevel@tonic-gate 			return (-1);
389*7c478bd9Sstevel@tonic-gate 		}
390*7c478bd9Sstevel@tonic-gate 	}
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 	for (cyl = start_cyl; cyl < (int32_t)end_cyl; cyl++) {
393*7c478bd9Sstevel@tonic-gate 		/*
394*7c478bd9Sstevel@tonic-gate 		 * This is not the optimal ioctl to format the floppy.
395*7c478bd9Sstevel@tonic-gate 		 * The device driver should do do the work,
396*7c478bd9Sstevel@tonic-gate 		 * instead of this program mucking with a lot
397*7c478bd9Sstevel@tonic-gate 		 * of low-level, device-dependent code.
398*7c478bd9Sstevel@tonic-gate 		 */
399*7c478bd9Sstevel@tonic-gate 		fdr_seek.fdr_cmd[2] = cyl;
400*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, FDRAW, &fdr_seek) < 0) {
401*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
402*7c478bd9Sstevel@tonic-gate 			    gettext(" seek to cyl %d failed\n"),
403*7c478bd9Sstevel@tonic-gate 			    cyl);
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 			/* restore the default characteristics */
406*7c478bd9Sstevel@tonic-gate 			restore_default_chars(fd, save_fdchar, save_allmap);
407*7c478bd9Sstevel@tonic-gate 			return (-1);
408*7c478bd9Sstevel@tonic-gate 		}
409*7c478bd9Sstevel@tonic-gate 		/*
410*7c478bd9Sstevel@tonic-gate 		 * Assume that the fd driver has issued a SENSE_INT
411*7c478bd9Sstevel@tonic-gate 		 * command to complete the seek operation.
412*7c478bd9Sstevel@tonic-gate 		 */
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 		for (hd = start_head; hd < end_head; hd++) {
415*7c478bd9Sstevel@tonic-gate 			p = (uchar_t *)fbuf;
416*7c478bd9Sstevel@tonic-gate 			for (i = 1; i <= spt; i++) {
417*7c478bd9Sstevel@tonic-gate 				*p++ = (uchar_t)cyl;
418*7c478bd9Sstevel@tonic-gate 				*p++ = (uchar_t)hd;
419*7c478bd9Sstevel@tonic-gate 				*p++ = (uchar_t)i; /* sector # */
420*7c478bd9Sstevel@tonic-gate 				*p++ = (sec_size == 1024) ? 3 : 2;
421*7c478bd9Sstevel@tonic-gate 			}
422*7c478bd9Sstevel@tonic-gate 			/*
423*7c478bd9Sstevel@tonic-gate 			 * ASSUME the fd driver is going to set drive-select
424*7c478bd9Sstevel@tonic-gate 			 * bits in the second command byte
425*7c478bd9Sstevel@tonic-gate 			 */
426*7c478bd9Sstevel@tonic-gate 			fdr_form.fdr_cmd[1] = hd << 2;
427*7c478bd9Sstevel@tonic-gate 			fdr_form.fdr_cmd[2] = (sec_size == 1024) ? 3 : 2;
428*7c478bd9Sstevel@tonic-gate 			fdr_form.fdr_cmd[3] = spt;
429*7c478bd9Sstevel@tonic-gate 			fdr_form.fdr_cmd[4] = gap;
430*7c478bd9Sstevel@tonic-gate 			fdr_form.fdr_nbytes = 4 * spt;
431*7c478bd9Sstevel@tonic-gate 			fdr_form.fdr_addr = (char *)fbuf;
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 			if (ioctl(fd, FDRAW, &fdr_form) < 0) {
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
437*7c478bd9Sstevel@tonic-gate 					gettext(
438*7c478bd9Sstevel@tonic-gate 					"format of cyl %d head %d failed\n"),
439*7c478bd9Sstevel@tonic-gate 						cyl, hd);
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 				/* restore the default characteristics */
442*7c478bd9Sstevel@tonic-gate 				restore_default_chars(fd, save_fdchar,
443*7c478bd9Sstevel@tonic-gate 				    save_allmap);
444*7c478bd9Sstevel@tonic-gate 				return (-1);
445*7c478bd9Sstevel@tonic-gate 			}
446*7c478bd9Sstevel@tonic-gate 			if (fdr_form.fdr_result[0] & 0xC0) {
447*7c478bd9Sstevel@tonic-gate 				if (fdr_form.fdr_result[1] & 0x02) {
448*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, gettext(
449*7c478bd9Sstevel@tonic-gate 					/*CSTYLED*/
450*7c478bd9Sstevel@tonic-gate 					"diskette is write protected\n"));
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 					/*
453*7c478bd9Sstevel@tonic-gate 					 * restore the default
454*7c478bd9Sstevel@tonic-gate 					 * characteristics
455*7c478bd9Sstevel@tonic-gate 					 */
456*7c478bd9Sstevel@tonic-gate 					restore_default_chars(fd, save_fdchar,
457*7c478bd9Sstevel@tonic-gate 					    save_allmap);
458*7c478bd9Sstevel@tonic-gate 					return (-1);
459*7c478bd9Sstevel@tonic-gate 				}
460*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
461*7c478bd9Sstevel@tonic-gate 					gettext(
462*7c478bd9Sstevel@tonic-gate 					"format of cyl %d head %d failed\n"),
463*7c478bd9Sstevel@tonic-gate 						cyl, hd);
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 				/* restore the default characteristics */
466*7c478bd9Sstevel@tonic-gate 				restore_default_chars(fd, save_fdchar,
467*7c478bd9Sstevel@tonic-gate 				    save_allmap);
468*7c478bd9Sstevel@tonic-gate 				return (-1);
469*7c478bd9Sstevel@tonic-gate 			}
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 		}
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 		/*
474*7c478bd9Sstevel@tonic-gate 		 *  do a quick verify
475*7c478bd9Sstevel@tonic-gate 		 */
476*7c478bd9Sstevel@tonic-gate 		if (llseek(fd, cyl * cyl_size, 0) != cyl * cyl_size) {
477*7c478bd9Sstevel@tonic-gate 			PERROR(" bad seek to format verify, ");
478*7c478bd9Sstevel@tonic-gate 			/* restore the default characteristics */
479*7c478bd9Sstevel@tonic-gate 			restore_default_chars(fd, save_fdchar,
480*7c478bd9Sstevel@tonic-gate 			    save_allmap);
481*7c478bd9Sstevel@tonic-gate 			return (-1);
482*7c478bd9Sstevel@tonic-gate 		}
483*7c478bd9Sstevel@tonic-gate 		if (fdchar.fdc_nhead == end_head) {
484*7c478bd9Sstevel@tonic-gate 			if (read(fd, obuf, cyl_size) != cyl_size) {
485*7c478bd9Sstevel@tonic-gate 				PERROR("Could not read format data");
486*7c478bd9Sstevel@tonic-gate 				/* restore the default characteristics */
487*7c478bd9Sstevel@tonic-gate 				restore_default_chars(fd, save_fdchar,
488*7c478bd9Sstevel@tonic-gate 				    save_allmap);
489*7c478bd9Sstevel@tonic-gate 				return (-1);
490*7c478bd9Sstevel@tonic-gate 			}
491*7c478bd9Sstevel@tonic-gate 		}
492*7c478bd9Sstevel@tonic-gate 	}
493*7c478bd9Sstevel@tonic-gate 	if (llseek(fd, (off_t)0, 0) != 0) {
494*7c478bd9Sstevel@tonic-gate 		PERROR("seek to blk 0 failed");
495*7c478bd9Sstevel@tonic-gate 		/* restore the default characteristics */
496*7c478bd9Sstevel@tonic-gate 		restore_default_chars(fd, save_fdchar, save_allmap);
497*7c478bd9Sstevel@tonic-gate 		return (-1);
498*7c478bd9Sstevel@tonic-gate 	}
499*7c478bd9Sstevel@tonic-gate 	return (0);
500*7c478bd9Sstevel@tonic-gate }
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate /*
504*7c478bd9Sstevel@tonic-gate  * Restore the default characteristics of the floppy diskette.
505*7c478bd9Sstevel@tonic-gate  * Fdformat changes the characteristics in the process of formatting.
506*7c478bd9Sstevel@tonic-gate  * If fdformat fails while in the process of doing the format, fdformat
507*7c478bd9Sstevel@tonic-gate  * should clean up after itself and reset the driver back to the original
508*7c478bd9Sstevel@tonic-gate  * state.
509*7c478bd9Sstevel@tonic-gate  */
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate static void
restore_default_chars(int32_t fd,struct fd_char save_fdchar,struct dk_allmap save_allmap)512*7c478bd9Sstevel@tonic-gate restore_default_chars(int32_t fd,
513*7c478bd9Sstevel@tonic-gate 			struct fd_char save_fdchar,
514*7c478bd9Sstevel@tonic-gate 			struct dk_allmap save_allmap)
515*7c478bd9Sstevel@tonic-gate {
516*7c478bd9Sstevel@tonic-gate 
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	/*
519*7c478bd9Sstevel@tonic-gate 	 * When this function is called, fdformat is failing anyways,
520*7c478bd9Sstevel@tonic-gate 	 * so the errors are not processed.
521*7c478bd9Sstevel@tonic-gate 	 */
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	(void) ioctl(fd, FDIOSCHAR, &save_fdchar);
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	(void) ioctl(fd, DKIOCSAPART, &save_allmap);
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 	/*
528*7c478bd9Sstevel@tonic-gate 	 * Before looking at the diskette's characteristics, format_floppy()
529*7c478bd9Sstevel@tonic-gate 	 * sets the x86 floppy driver to the default characteristics.
530*7c478bd9Sstevel@tonic-gate 	 * restore drive to default geometry and
531*7c478bd9Sstevel@tonic-gate 	 * characteristics.  This ioctl isn't implemented on
532*7c478bd9Sstevel@tonic-gate 	 * sparc.
533*7c478bd9Sstevel@tonic-gate 	 */
534*7c478bd9Sstevel@tonic-gate 	(void) ioctl(fd, FDDEFGEOCHAR, NULL);
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate }
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate int32_t
_m_media_format(rmedia_handle_t * handle,void * ip)539*7c478bd9Sstevel@tonic-gate _m_media_format(rmedia_handle_t *handle, void *ip) {
540*7c478bd9Sstevel@tonic-gate 	struct format_track ft;
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 	/* Check for valid handle */
543*7c478bd9Sstevel@tonic-gate 	if (handle == NULL) {
544*7c478bd9Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
545*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
546*7c478bd9Sstevel@tonic-gate 		return (-1);
547*7c478bd9Sstevel@tonic-gate 	}
548*7c478bd9Sstevel@tonic-gate 	if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
549*7c478bd9Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
550*7c478bd9Sstevel@tonic-gate 		DPRINTF2(
551*7c478bd9Sstevel@tonic-gate 			"Signature expected=0x%x, found=0x%x\n",
552*7c478bd9Sstevel@tonic-gate 				LIBSMEDIA_SIGNATURE, handle->sm_signature);
553*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
554*7c478bd9Sstevel@tonic-gate 		return (-1);
555*7c478bd9Sstevel@tonic-gate 	}
556*7c478bd9Sstevel@tonic-gate 	if (handle->sm_fd < 0) {
557*7c478bd9Sstevel@tonic-gate 		DPRINTF("Invalid file handle.\n");
558*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
559*7c478bd9Sstevel@tonic-gate 		return (-1);
560*7c478bd9Sstevel@tonic-gate 	}
561*7c478bd9Sstevel@tonic-gate 	DPRINTF("Format floppy called \n");
562*7c478bd9Sstevel@tonic-gate 	ft.track_no = (-1);
563*7c478bd9Sstevel@tonic-gate 	ft.head = (-1);
564*7c478bd9Sstevel@tonic-gate 	ft.flag = ((struct format_flags *)ip)->flavor;
565*7c478bd9Sstevel@tonic-gate 	return (format_floppy(handle->sm_fd, &ft));
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate }
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate int32_t
_m_media_format_track(rmedia_handle_t * handle,void * ip)570*7c478bd9Sstevel@tonic-gate _m_media_format_track(rmedia_handle_t *handle, void *ip)
571*7c478bd9Sstevel@tonic-gate {
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 	/* Check for valid handle */
574*7c478bd9Sstevel@tonic-gate 	if (handle == NULL) {
575*7c478bd9Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
576*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
577*7c478bd9Sstevel@tonic-gate 		return (-1);
578*7c478bd9Sstevel@tonic-gate 	}
579*7c478bd9Sstevel@tonic-gate 	if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
580*7c478bd9Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
581*7c478bd9Sstevel@tonic-gate 		DPRINTF2(
582*7c478bd9Sstevel@tonic-gate 			"Signature expected=0x%x, found=0x%x\n",
583*7c478bd9Sstevel@tonic-gate 				LIBSMEDIA_SIGNATURE, handle->sm_signature);
584*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
585*7c478bd9Sstevel@tonic-gate 		return (-1);
586*7c478bd9Sstevel@tonic-gate 	}
587*7c478bd9Sstevel@tonic-gate 	if (handle->sm_fd < 0) {
588*7c478bd9Sstevel@tonic-gate 		DPRINTF("Invalid file handle.\n");
589*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
590*7c478bd9Sstevel@tonic-gate 		return (-1);
591*7c478bd9Sstevel@tonic-gate 	}
592*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
593*7c478bd9Sstevel@tonic-gate 	if (ip != NULL) {
594*7c478bd9Sstevel@tonic-gate 		struct format_track *ft = (struct format_track *)ip;
595*7c478bd9Sstevel@tonic-gate 		DPRINTF2("Format track %d head %d\n", ft->track_no, ft->head);
596*7c478bd9Sstevel@tonic-gate 	}
597*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */
598*7c478bd9Sstevel@tonic-gate 	return (format_floppy(handle->sm_fd, ip));
599*7c478bd9Sstevel@tonic-gate }
600