#include <stdio.h>
#include <sys/types.h>
#include <sys/dklabel.h>
#include <sys/dkio.h>
#include <sys/fdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <locale.h>
#include <errno.h>
#include <sys/param.h>
#include <stdlib.h>
#include <sys/smedia.h>
#include "../../../library/inc/rmedia.h"
#include "f_defines.h"
extern void my_perror(char *err_string);
static void restore_default_chars(int32_t fd,
struct fd_char save_fdchar,
struct dk_allmap save_allmap);
static int32_t
format_floppy(int32_t fd, void *ip)
{
struct format_track *ft = (struct format_track *)ip;
int32_t format_flags;
int32_t transfer_rate = 1000;
int32_t sec_size = 512;
uchar_t gap = 0x54;
uchar_t *fbuf, *p;
int32_t cyl_size;
int32_t i;
int32_t chgd;
int32_t cyl, hd;
int32_t size_of_part, size_of_dev;
int32_t spt = 36;
int32_t drive_size;
uchar_t num_cyl = 80;
struct fd_char save_fdchar;
struct dk_allmap save_allmap;
int32_t D_flag = 0;
int32_t E_flag = 0;
int32_t H_flag = 0;
int32_t M_flag = 0;
struct fd_char fdchar;
struct dk_geom fdgeom;
struct dk_allmap allmap;
struct dk_cinfo dkinfo;
int32_t start_head, end_head, start_cyl, end_cyl;
static uchar_t *obuf;
struct fd_raw fdr_seek = {
FDRAW_SEEK, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0
};
struct fd_raw fdr_form = {
0x4D, 0, 2, 0, 0x54, (char)0xA5, 0, 0, 0, 0,
6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0
};
format_flags = ft->flag;
DPRINTF1("Format flag is %d\n", format_flags);
if (format_flags == SM_FORMAT_HD) {
H_flag = 1;
} else if (format_flags == SM_FORMAT_DD) {
D_flag = 1;
} else if (format_flags == SM_FORMAT_ED) {
E_flag = 1;
} else if (format_flags == SM_FORMAT_MD) {
M_flag = 1;
} else {
DPRINTF("Invalid operation \n");
errno = ENOTSUP;
return (-1);
}
(void) ioctl(fd, FDDEFGEOCHAR, NULL);
if (ioctl(fd, DKIOCINFO, &dkinfo) < 0) {
PERROR("DKIOCINFO failed.");
exit(3);
}
if (ioctl(fd, DKIOCGAPART, &allmap) < 0) {
PERROR("DKIOCGAPART failed.");
return (-1);
}
save_allmap = allmap;
if (ioctl(fd, FDIOGCHAR, &fdchar) < 0) {
PERROR("FDIOGCHAR failed.");
return (-1);
}
save_fdchar = fdchar;
size_of_part = allmap.dka_map[dkinfo.dki_partition].dkl_nblk
* DEV_BSIZE;
size_of_dev = fdchar.fdc_ncyl * fdchar.fdc_nhead
* fdchar.fdc_secptrack * fdchar.fdc_sec_size;
if (size_of_part != size_of_dev) {
DPRINTF("The entire diskette must be formatted\n");
DPRINTF1("size_of_part %d\n", size_of_part);
DPRINTF1("size_of_dev %d\n", size_of_dev);
errno = ENOTSUP;
return (-1);
}
if (ioctl(fd, DKIOCGGEOM, &fdgeom) < 0) {
PERROR("DKIOCGGEOM failed.");
return (-1);
}
#ifdef sparc
fdchar.fdc_medium = 3;
#endif
if (fdchar.fdc_medium == 5)
drive_size = 5;
else
drive_size = 3;
if ((E_flag | H_flag | D_flag | M_flag) == 0) {
switch (fdchar.fdc_transfer_rate) {
case 1000:
E_flag++;
break;
case 500:
default:
H_flag++;
break;
#ifndef sparc
case 250:
D_flag++;
break;
#endif
}
}
if (H_flag) {
transfer_rate = 500;
num_cyl = 80;
sec_size = 512;
if (drive_size == 5) {
spt = 15;
} else {
spt = 18;
}
gap = 0x54;
} else if (D_flag) {
transfer_rate = 250;
if (drive_size == 5) {
if (fdchar.fdc_transfer_rate == 500) {
transfer_rate = 300;
fdchar.fdc_steps = 2;
}
num_cyl = 40;
gap = 0x50;
} else {
num_cyl = 80;
gap = 0x54;
}
sec_size = 512;
spt = 9;
} else if (M_flag) {
#ifdef sparc
transfer_rate = 500;
#else
transfer_rate = 417;
#endif
num_cyl = 77;
sec_size = 1024;
spt = 8;
gap = 0x74;
} else if (E_flag) {
transfer_rate = 1000;
num_cyl = 80;
sec_size = 512;
spt = 36;
gap = 0x54;
}
if (allmap.dka_map[2].dkl_nblk !=
(2 * num_cyl * spt * (M_flag ? 2 : 1))) {
allmap.dka_map[1].dkl_cylno = num_cyl - 1;
allmap.dka_map[0].dkl_nblk = 2 * (num_cyl - 1) * spt *
(M_flag ? 2 : 1);
allmap.dka_map[1].dkl_nblk = 2 * spt * (M_flag ? 2 : 1);
allmap.dka_map[2].dkl_nblk = 2 * num_cyl * spt *
(M_flag ? 2 : 1);
if (allmap.dka_map[3].dkl_nblk)
allmap.dka_map[3].dkl_nblk = 2 * (num_cyl - 1) * spt *
(M_flag ? 2 : 1);
if (allmap.dka_map[4].dkl_nblk)
allmap.dka_map[4].dkl_nblk =
2 * spt * (M_flag ? 2 : 1);
}
#ifndef sparc
if (num_cyl > fdchar.fdc_ncyl || spt > fdchar.fdc_secptrack ||
transfer_rate > fdchar.fdc_transfer_rate) {
PERROR("drive not capable of requested density");
return (-1);
}
#endif
if (num_cyl != fdchar.fdc_ncyl || spt != fdchar.fdc_secptrack ||
transfer_rate != fdchar.fdc_transfer_rate) {
#ifdef sparc
fdchar.fdc_medium = M_flag ? 1 : 0;
#endif
fdchar.fdc_transfer_rate = transfer_rate;
fdchar.fdc_ncyl = num_cyl;
fdchar.fdc_sec_size = sec_size;
fdchar.fdc_secptrack = spt;
if (ioctl(fd, FDIOSCHAR, &fdchar) < 0) {
PERROR("FDIOSCHAR (density selection) failed");
restore_default_chars(fd, save_fdchar, save_allmap);
return (-1);
}
if (ioctl(fd, DKIOCSAPART, &allmap) < 0) {
PERROR("DKIOCSAPART failed");
restore_default_chars(fd, save_fdchar, save_allmap);
return (-1);
}
}
cyl_size = 2 * sec_size * spt;
if ((obuf = (uchar_t *)malloc((size_t)cyl_size)) == 0) {
PERROR("car't malloc verify buffer");
restore_default_chars(fd, save_fdchar, save_allmap);
return (-1);
}
if (ioctl(fd, FDGETCHANGE, &chgd) == 0) {
if (chgd & FDGC_CURRENT) {
(void) fprintf(stderr,
gettext("no diskette in drive \n"));
restore_default_chars(fd, save_fdchar, save_allmap);
return (-1);
}
if (chgd & FDGC_CURWPROT) {
(void) fprintf(stderr,
gettext("Media is write protected\n"));
restore_default_chars(fd, save_fdchar, save_allmap);
return (-1);
}
}
if ((fbuf = (uchar_t *)malloc((unsigned)(4 * spt))) == 0) {
PERROR("Could not malloc format header buffer");
restore_default_chars(fd, save_fdchar, save_allmap);
return (-1);
}
if (ft->track_no == -1) {
start_cyl = 0;
end_cyl = num_cyl;
start_head = 0;
end_head = fdchar.fdc_nhead;
} else {
start_cyl = ft->track_no;
end_cyl = ft->track_no + 1;
start_head = ft->head;
end_head = ft->head + 1;
if ((end_cyl > num_cyl) || (end_head > fdchar.fdc_nhead)) {
errno = EINVAL;
return (-1);
}
}
for (cyl = start_cyl; cyl < (int32_t)end_cyl; cyl++) {
fdr_seek.fdr_cmd[2] = cyl;
if (ioctl(fd, FDRAW, &fdr_seek) < 0) {
(void) fprintf(stderr,
gettext(" seek to cyl %d failed\n"),
cyl);
restore_default_chars(fd, save_fdchar, save_allmap);
return (-1);
}
for (hd = start_head; hd < end_head; hd++) {
p = (uchar_t *)fbuf;
for (i = 1; i <= spt; i++) {
*p++ = (uchar_t)cyl;
*p++ = (uchar_t)hd;
*p++ = (uchar_t)i;
*p++ = (sec_size == 1024) ? 3 : 2;
}
fdr_form.fdr_cmd[1] = hd << 2;
fdr_form.fdr_cmd[2] = (sec_size == 1024) ? 3 : 2;
fdr_form.fdr_cmd[3] = spt;
fdr_form.fdr_cmd[4] = gap;
fdr_form.fdr_nbytes = 4 * spt;
fdr_form.fdr_addr = (char *)fbuf;
if (ioctl(fd, FDRAW, &fdr_form) < 0) {
(void) fprintf(stderr,
gettext(
"format of cyl %d head %d failed\n"),
cyl, hd);
restore_default_chars(fd, save_fdchar,
save_allmap);
return (-1);
}
if (fdr_form.fdr_result[0] & 0xC0) {
if (fdr_form.fdr_result[1] & 0x02) {
(void) fprintf(stderr, gettext(
"diskette is write protected\n"));
restore_default_chars(fd, save_fdchar,
save_allmap);
return (-1);
}
(void) fprintf(stderr,
gettext(
"format of cyl %d head %d failed\n"),
cyl, hd);
restore_default_chars(fd, save_fdchar,
save_allmap);
return (-1);
}
}
if (llseek(fd, cyl * cyl_size, 0) != cyl * cyl_size) {
PERROR(" bad seek to format verify, ");
restore_default_chars(fd, save_fdchar,
save_allmap);
return (-1);
}
if (fdchar.fdc_nhead == end_head) {
if (read(fd, obuf, cyl_size) != cyl_size) {
PERROR("Could not read format data");
restore_default_chars(fd, save_fdchar,
save_allmap);
return (-1);
}
}
}
if (llseek(fd, (off_t)0, 0) != 0) {
PERROR("seek to blk 0 failed");
restore_default_chars(fd, save_fdchar, save_allmap);
return (-1);
}
return (0);
}
static void
restore_default_chars(int32_t fd,
struct fd_char save_fdchar,
struct dk_allmap save_allmap)
{
(void) ioctl(fd, FDIOSCHAR, &save_fdchar);
(void) ioctl(fd, DKIOCSAPART, &save_allmap);
(void) ioctl(fd, FDDEFGEOCHAR, NULL);
}
int32_t
_m_media_format(rmedia_handle_t *handle, void *ip) {
struct format_track ft;
if (handle == NULL) {
DPRINTF("Null Handle\n");
errno = EINVAL;
return (-1);
}
if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
DPRINTF("Invalid signature in handle.\n");
DPRINTF2(
"Signature expected=0x%x, found=0x%x\n",
LIBSMEDIA_SIGNATURE, handle->sm_signature);
errno = EINVAL;
return (-1);
}
if (handle->sm_fd < 0) {
DPRINTF("Invalid file handle.\n");
errno = EINVAL;
return (-1);
}
DPRINTF("Format floppy called \n");
ft.track_no = (-1);
ft.head = (-1);
ft.flag = ((struct format_flags *)ip)->flavor;
return (format_floppy(handle->sm_fd, &ft));
}
int32_t
_m_media_format_track(rmedia_handle_t *handle, void *ip)
{
if (handle == NULL) {
DPRINTF("Null Handle\n");
errno = EINVAL;
return (-1);
}
if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
DPRINTF("Invalid signature in handle.\n");
DPRINTF2(
"Signature expected=0x%x, found=0x%x\n",
LIBSMEDIA_SIGNATURE, handle->sm_signature);
errno = EINVAL;
return (-1);
}
if (handle->sm_fd < 0) {
DPRINTF("Invalid file handle.\n");
errno = EINVAL;
return (-1);
}
#ifdef DEBUG
if (ip != NULL) {
struct format_track *ft = (struct format_track *)ip;
DPRINTF2("Format track %d head %d\n", ft->track_no, ft->head);
}
#endif
return (format_floppy(handle->sm_fd, ip));
}