xref: /illumos-gate/usr/src/lib/libsmedia/plugins/floppy/common/f_generic.c (revision 440a8a36792bdf9ef51639066aab0b7771ffcab8)
1 /*
2  * CDDL HEADER START
3  *
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
7  * with the License.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * f_generic.c :
31  *      This file contains all the functionalities except format of
32  *	floppy plug-in for libsm.so.
33  */
34 
35 #include <sys/types.h>
36 #include <sys/fdio.h>
37 #include <stdlib.h>
38 #include <sys/smedia.h>
39 #include "../../../library/inc/rmedia.h"
40 #include "f_defines.h"
41 
42 
43 void
44 my_perror(char *err_string)
45 {
46 
47 	int error_no;
48 	if (errno == 0)
49 		return;
50 
51 	error_no = errno;
52 	(void) fprintf(stderr, gettext(err_string));
53 	(void) fprintf(stderr, gettext(" : "));
54 	errno = error_no;
55 	perror("");
56 }
57 
58 int32_t
59 _m_device_type(ushort_t ctype, ushort_t mtype)
60 {
61 	if ((ctype == DKC_INTEL82077) || (ctype == DKC_UNKNOWN)) {
62 		if (mtype == 0)
63 			return (0);
64 	}
65 	return (-1);
66 }
67 
68 int32_t
69 _m_version_no(void)
70 {
71 	return (SM_FD_VERSION_1);
72 }
73 
74 int32_t
75 _m_get_media_info(rmedia_handle_t *handle, void *ip)
76 {
77 	smmedium_prop_t *med_info = (smmedium_prop_t *)ip;
78 struct fd_char fdchar;
79 
80 	/* Check for valid handle */
81 	if (handle == NULL) {
82 		DPRINTF("Null Handle\n");
83 		errno = EINVAL;
84 		return (-1);
85 	}
86 	if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
87 		DPRINTF("Invalid signature in handle.\n");
88 		DPRINTF2(
89 			"Signature expected=0x%x found=0x%x\n",
90 				LIBSMEDIA_SIGNATURE,
91 				handle->sm_signature);
92 		errno = EINVAL;
93 		return (-1);
94 	}
95 	if (handle->sm_fd < 0) {
96 		DPRINTF("Invalid file handle.\n");
97 		errno = EINVAL;
98 		return (-1);
99 	}
100 	if (ioctl(handle->sm_fd, FDIOGCHAR, &fdchar) < 0) {
101 		PERROR("Ioctl failed :");
102 		return (-1);
103 	}
104 
105 	med_info->sm_media_type = SM_FLOPPY;
106 	med_info->sm_blocksize  = fdchar.fdc_sec_size;
107 	med_info->sm_capacity = fdchar.fdc_ncyl * fdchar.fdc_nhead
108 					* fdchar.fdc_secptrack;
109 	med_info->sm_pcyl = fdchar.fdc_ncyl;
110 	med_info->sm_nhead = fdchar.fdc_nhead;
111 	med_info->sm_nsect = fdchar.fdc_secptrack;
112 	return (0);
113 }
114 
115 /* ARGSUSED0 */
116 int32_t
117 _m_get_device_info(rmedia_handle_t *handle, void *ip)
118 {
119 	smdevice_info_t *dev_info = (smdevice_info_t *)ip;
120 	char *vendor_name, *product_name, *fw_version;
121 
122 	/* Check for valid handle */
123 	if (handle == NULL) {
124 		DPRINTF("Null Handle\n");
125 		errno = EINVAL;
126 		return (-1);
127 	}
128 	if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
129 		DPRINTF("Invalid signature in handle.\n");
130 		DPRINTF2(
131 			"Signature expected=0x%x found=0x%x\n",
132 				LIBSMEDIA_SIGNATURE,
133 				handle->sm_signature);
134 		errno = EINVAL;
135 		return (-1);
136 	}
137 	if (handle->sm_fd < 0) {
138 		DPRINTF("Invalid file handle.\n");
139 		errno = EINVAL;
140 		return (-1);
141 	}
142 	vendor_name = (char *)malloc(1);
143 	if (vendor_name == NULL) {
144 		if (!errno)
145 			errno = ENOMEM;
146 		return (-1);
147 	}
148 	product_name = (char *)malloc(1);
149 	if (product_name == NULL) {
150 		free(vendor_name);
151 		if (!errno)
152 			errno = ENOMEM;
153 		return (-1);
154 	}
155 
156 	fw_version = (char *)malloc(1);
157 	if (fw_version == NULL) {
158 		free(vendor_name);
159 		free(product_name);
160 		if (!errno)
161 			errno = ENOMEM;
162 		return (-1);
163 	}
164 
165 	vendor_name[0] = 0;
166 	product_name[0] = 0;
167 	fw_version[0] = 0;
168 
169 	dev_info->sm_interface_type = IF_FLOPPY;
170 	dev_info->sm_vendor_name = vendor_name;
171 	dev_info->sm_product_name = product_name;
172 	dev_info->sm_firmware_version = fw_version;
173 
174 	return (0);
175 }
176 
177 int32_t
178 _m_free_device_info(rmedia_handle_t *handle, void *ip)
179 {
180 	struct smdevice_info *dev_info = ip;
181 
182 	/* Check for valid handle */
183 	if (handle == NULL) {
184 		DPRINTF("Null Handle\n");
185 		errno = EINVAL;
186 		return (-1);
187 	}
188 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
189 		DPRINTF("Invalid signature in handle.\n");
190 		errno = EINVAL;
191 		return (-1);
192 	}
193 
194 	free(dev_info->sm_vendor_name);
195 	free(dev_info->sm_product_name);
196 	free(dev_info->sm_firmware_version);
197 	return (0);
198 }
199 
200 /* ARGSUSED1 */
201 int32_t
202 _m_get_media_status(rmedia_handle_t *handle, void *ip)
203 {
204 	smwp_state_t	*wp = ip;
205 	int32_t j;
206 
207 	if (ioctl(handle->sm_fd, FDGETCHANGE, &j)) {
208 		return (-1);
209 	}
210 	if (j & FDGC_CURWPROT)
211 		wp->sm_new_state = SM_WRITE_PROTECT_NOPASSWD;
212 	else
213 		wp->sm_new_state = SM_WRITE_PROTECT_DISABLE;
214 	return (0);
215 }
216 
217 int32_t
218 _m_raw_read(rmedia_handle_t *handle, void *ip)
219 {
220 	struct raw_params *r_p = (struct raw_params *)ip;
221 
222 	int32_t	sector_size;
223 	int32_t ret_val;
224 	struct	fd_raw fdraw;
225 	struct	fd_char fdchar;
226 	int32_t cyl, rem, head, start_sector;
227 
228 
229 	/* Check for valid handle */
230 	if (handle == NULL) {
231 		DPRINTF("Null Handle\n");
232 		errno = EINVAL;
233 		return (-1);
234 	}
235 	if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
236 		DPRINTF("Invalid signature in handle.\n");
237 		DPRINTF2(
238 			"Signature expected=0x%x found=0x%x\n",
239 				LIBSMEDIA_SIGNATURE,
240 				handle->sm_signature);
241 		errno = EINVAL;
242 		return (-1);
243 	}
244 	if (handle->sm_fd < 0) {
245 		DPRINTF("Invalid file handle.\n");
246 		errno = EINVAL;
247 		return (-1);
248 	}
249 	if (ioctl(handle->sm_fd, FDIOGCHAR, &fdchar) < 0) {
250 		PERROR("Ioctl failed :");
251 		return (-1);
252 	}
253 
254 	sector_size = fdchar.fdc_sec_size;
255 
256 	if ((!r_p->size) || (r_p->size % sector_size)) {
257 		errno = EINVAL;
258 		return (-1);
259 	}
260 
261 	cyl = r_p->offset/(fdchar.fdc_nhead * fdchar.fdc_secptrack);
262 	rem = r_p->offset%(fdchar.fdc_nhead * fdchar.fdc_secptrack);
263 	head = rem/fdchar.fdc_secptrack;
264 	start_sector = rem%fdchar.fdc_secptrack + 1;
265 
266 	fdraw.fdr_nbytes = r_p->size;
267 	fdraw.fdr_addr = r_p->buffer;
268 
269 
270 	fdraw.fdr_cmd[0] = (uint8_t)0xE0 | FDRAW_RDCMD;	/* command */
271 					/* MFM | MT | SK| FDRAW_RDCMD */
272 	fdraw.fdr_cmd[1] = (head << 2);		/* using head 1 */
273 	fdraw.fdr_cmd[2] = cyl;		/* track number */
274 	fdraw.fdr_cmd[3] = head;		/* drive head number */
275 	fdraw.fdr_cmd[4] = start_sector;	/* start sector number */
276 	fdraw.fdr_cmd[5] = (sector_size == 512) ? 2 : 3;
277 	fdraw.fdr_cmd[6] = fdchar.fdc_secptrack;
278 	fdraw.fdr_cmd[7] = 0x1B; 	/* GPLN, GAP length */
279 	fdraw.fdr_cmd[8] = (uchar_t)0xFF; 	/* SSSDTL, data length */
280 	fdraw.fdr_cnum = 0x9; 	/* NCBRW, no. cmd bytes defined in fdreg.h */
281 
282 	errno = 0;
283 	ret_val = ioctl(handle->sm_fd, FDRAW, &fdraw);
284 	if (ret_val < 0) {
285 		PERROR("RAW READ failed:");
286 		return (-1);
287 	}
288 
289 	return (fdraw.fdr_nbytes);
290 }
291 int32_t
292 _m_raw_write(rmedia_handle_t *handle, void *ip)
293 {
294 	struct raw_params *r_p = (struct raw_params *)ip;
295 
296 	int32_t	sector_size;
297 	int32_t ret_val;
298 	struct	fd_raw fdraw;
299 	struct	fd_char fdchar;
300 	int32_t cyl, rem, head, start_sector;
301 
302 
303 	/* Check for valid handle */
304 	if (handle == NULL) {
305 		DPRINTF("Null Handle\n");
306 		errno = EINVAL;
307 		return (-1);
308 	}
309 	if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
310 		DPRINTF("Invalid signature in handle.\n");
311 		DPRINTF2(
312 			"Signature expected=0x%x, found=0x%x\n",
313 				LIBSMEDIA_SIGNATURE, handle->sm_signature);
314 		errno = EINVAL;
315 		return (-1);
316 	}
317 	if (handle->sm_fd < 0) {
318 		DPRINTF("Invalid file handle.\n");
319 		errno = EINVAL;
320 		return (-1);
321 	}
322 	if (ioctl(handle->sm_fd, FDIOGCHAR, &fdchar) < 0) {
323 		PERROR("Ioctl failed :");
324 		return (-1);
325 	}
326 
327 	sector_size = fdchar.fdc_sec_size;
328 
329 	if ((!r_p->size) || (r_p->size % sector_size)) {
330 		errno = EINVAL;
331 		return (-1);
332 	}
333 
334 	cyl = r_p->offset/(fdchar.fdc_nhead * fdchar.fdc_secptrack);
335 	rem = r_p->offset%(fdchar.fdc_nhead * fdchar.fdc_secptrack);
336 	head = rem/fdchar.fdc_secptrack;
337 	start_sector = rem%fdchar.fdc_secptrack + 1;
338 
339 	fdraw.fdr_nbytes = r_p->size;
340 	fdraw.fdr_addr = r_p->buffer;
341 
342 
343 	fdraw.fdr_cmd[0] = (uint8_t)0xE0| FDRAW_WRCMD;	/* command */
344 				/* MFM | MT | SK| FDRAW_WRCMD;	*/
345 	fdraw.fdr_cmd[1] = (head << 2);		/* using head 1 */
346 	fdraw.fdr_cmd[2] = cyl;		/* track number */
347 	fdraw.fdr_cmd[3] = head;		/* drive head number */
348 	fdraw.fdr_cmd[4] = start_sector;	/* start sector number */
349 	fdraw.fdr_cmd[5] = (sector_size == 512) ? 2 : 3;
350 	fdraw.fdr_cmd[6] = fdchar.fdc_secptrack;
351 	fdraw.fdr_cmd[7] = 0x1B;	/* GPLN, GAP length */
352 	fdraw.fdr_cmd[8] = (uchar_t)0xFF; 	/* SSSDTL, data length */
353 	fdraw.fdr_cnum = 0x9;	/* NCBRW, no. cmd bytes defined in fdreg.h */
354 
355 	errno = 0;
356 	ret_val = ioctl(handle->sm_fd, FDRAW, &fdraw);
357 	if (ret_val < 0) {
358 		PERROR("RAW READ failed:");
359 		return (-1);
360 	}
361 
362 	return (fdraw.fdr_nbytes);
363 }
364 
365 /* ARGSUSED */
366 int32_t
367 _m_eject(rmedia_handle_t *handle, void *ip)
368 {
369 
370 	/* Check for valid handle */
371 	if (handle == NULL) {
372 		DPRINTF("Null Handle\n");
373 		errno = EINVAL;
374 		return (-1);
375 	}
376 	if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
377 		DPRINTF("Invalid signature in handle.\n");
378 		DPRINTF2(
379 		"Signature expected=0x%x found=0x%x\n",
380 			LIBSMEDIA_SIGNATURE, handle->sm_signature);
381 		errno = EINVAL;
382 		return (-1);
383 	}
384 	if (handle->sm_fd < 0) {
385 		DPRINTF("Invalid file handle.\n");
386 		errno = EINVAL;
387 		return (-1);
388 	}
389 #ifdef sparc
390 	return (ioctl(handle->sm_fd, FDEJECT));
391 #else
392 	errno = ENOTSUP;
393 	return (-1);
394 #endif
395 }
396