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