2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2001 Joerg Wunsch
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <dev/ic/nec765.h>
33 #include <sys/fdcio.h>
44 * Decode the FDC status pointed to by `fdcsp', and print a textual
45 * translation to stderr. If `terse' is false, the numerical FDC
46 * register status is printed, too.
49 printstatus(struct fdc_status *fdcsp, int terse)
55 "\nFDC status ST0=%#x ST1=%#x ST2=%#x C=%u H=%u R=%u N=%u:\n",
56 fdcsp->status[0] & 0xff,
57 fdcsp->status[1] & 0xff,
58 fdcsp->status[2] & 0xff,
59 fdcsp->status[3] & 0xff,
60 fdcsp->status[4] & 0xff,
61 fdcsp->status[5] & 0xff,
62 fdcsp->status[6] & 0xff);
64 if ((fdcsp->status[0] & NE7_ST0_IC_RC) == 0) {
65 sprintf(msgbuf, "timeout");
66 } else if ((fdcsp->status[0] & NE7_ST0_IC_RC) != NE7_ST0_IC_AT) {
67 sprintf(msgbuf, "unexcpted interrupt code %#x",
68 fdcsp->status[0] & NE7_ST0_IC_RC);
70 strcpy(msgbuf, "unexpected error code in ST1/ST2");
72 if (fdcsp->status[1] & NE7_ST1_EN)
73 strcpy(msgbuf, "end of cylinder (wrong format)");
74 else if (fdcsp->status[1] & NE7_ST1_DE) {
75 if (fdcsp->status[2] & NE7_ST2_DD)
76 strcpy(msgbuf, "CRC error in data field");
78 strcpy(msgbuf, "CRC error in ID field");
79 } else if (fdcsp->status[1] & NE7_ST1_MA) {
80 if (fdcsp->status[2] & NE7_ST2_MD)
81 strcpy(msgbuf, "no address mark in data field");
83 strcpy(msgbuf, "no address mark in ID field");
84 } else if (fdcsp->status[2] & NE7_ST2_WC)
85 strcpy(msgbuf, "wrong cylinder (format mismatch)");
86 else if (fdcsp->status[1] & NE7_ST1_ND)
87 strcpy(msgbuf, "no data (sector not found)");
89 fputs(msgbuf, stderr);
92 static struct fd_type fd_types_auto[1] =
93 { { 0,0,0,0,0,0,0,0,0,0,0,FL_AUTO } };
96 static struct fd_type fd_types_288m[] = {
109 { 0,0,0,0,0,0,0,0,0,0,0,0 }
112 static struct fd_type fd_types_144m[] = {
120 { 0,0,0,0,0,0,0,0,0,0,0,0 }
129 { 0,0,0,0,0,0,0,0,0,0,0,0 }
133 static struct fd_type fd_types_12m[] = {
140 { 0,0,0,0,0,0,0,0,0,0,0,0 }
149 { FDF_5_360 | FL_2STEP },
151 { 0,0,0,0,0,0,0,0,0,0,0,0 }
155 static struct fd_type fd_types_720k[] =
160 { 0,0,0,0,0,0,0,0,0,0,0,0 }
163 static struct fd_type fd_types_360k[] =
168 { 0,0,0,0,0,0,0,0,0,0,0,0 }
173 * Parse a format string, and fill in the parameter pointed to by `out'.
175 * sectrac,secsize,datalen,gap,ncyls,speed,heads,f_gap,f_inter,offs2,flags[...]
177 * sectrac = sectors per track
178 * secsize = sector size in bytes
179 * datalen = length of sector if secsize == 128
180 * gap = gap length when reading
181 * ncyls = number of cylinders
182 * speed = transfer speed 250/300/500/1000 KB/s
183 * heads = number of heads
184 * f_gap = gap length when formatting
185 * f_inter = sector interleave when formatting
186 * offs2 = offset of sectors on side 2
187 * flags = +/-mfm | +/-2step | +/-perpend
188 * mfm - use MFM recording
189 * 2step - use 2 steps between cylinders
190 * perpend - user perpendicular (vertical) recording
192 * Any omitted value will be passed on from parameter `in'.
195 parse_fmt(const char *s, enum fd_drivetype type,
196 struct fd_type in, struct fd_type *out)
208 if ((cp = strchr(s, ',')) == NULL) {
214 s1 = malloc(cp - s + 1);
217 memcpy(s1, s, cp - s);
222 if (strlen(s1) == 0) {
228 case 0: /* sectrac */
229 if (getnum(s1, &out->sectrac))
231 "bad numeric value for sectrac: %s", s1);
234 case 1: /* secsize */
237 "bad numeric value for secsize: %s", s1);
238 if (j == 128) out->secsize = 0;
239 else if (j == 256) out->secsize = 1;
240 else if (j == 512) out->secsize = 2;
241 else if (j == 1024) out->secsize = 3;
243 errx(EX_USAGE, "bad sector size %d", j);
246 case 2: /* datalen */
249 "bad numeric value for datalen: %s", s1);
251 errx(EX_USAGE, "bad datalen %d", j);
256 if (getnum(s1, &out->gap))
258 "bad numeric value for gap: %s", s1);
264 "bad numeric value for ncyls: %s", s1);
266 errx(EX_USAGE, "bad # of cylinders %d", j);
273 "bad numeric value for speed: %s", s1);
276 abort(); /* paranoia */
281 out->trans = FDC_250KBPS;
283 errx(EX_USAGE, "bad speed %d", j);
288 out->trans = FDC_300KBPS;
290 out->trans = FDC_250KBPS;
292 out->trans = FDC_500KBPS;
294 errx(EX_USAGE, "bad speed %d", j);
299 out->trans = FDC_1MBPS;
303 out->trans = FDC_250KBPS;
305 out->trans = FDC_500KBPS;
307 errx(EX_USAGE, "bad speed %d", j);
315 "bad numeric value for heads: %s", s1);
316 if (j == 1 || j == 2)
319 errx(EX_USAGE, "bad # of heads %d", j);
323 if (getnum(s1, &out->f_gap))
325 "bad numeric value for f_gap: %s", s1);
328 case 8: /* f_inter */
329 if (getnum(s1, &out->f_inter))
331 "bad numeric value for f_inter: %s", s1);
335 if (getnum(s1, &out->offset_side2))
337 "bad numeric value for offs2: %s", s1);
341 if (strcmp(s1, "+mfm") == 0)
342 out->flags |= FL_MFM;
343 else if (strcmp(s1, "-mfm") == 0)
344 out->flags &= ~FL_MFM;
345 else if (strcmp(s1, "+auto") == 0)
346 out->flags |= FL_AUTO;
347 else if (strcmp(s1, "-auto") == 0)
348 out->flags &= ~FL_AUTO;
349 else if (strcmp(s1, "+2step") == 0)
350 out->flags |= FL_2STEP;
351 else if (strcmp(s1, "-2step") == 0)
352 out->flags &= ~FL_2STEP;
353 else if (strcmp(s1, "+perpnd") == 0)
354 out->flags |= FL_PERPND;
355 else if (strcmp(s1, "-perpnd") == 0)
356 out->flags &= ~FL_PERPND;
358 errx(EX_USAGE, "bad flag: %s", s1);
364 out->size = out->tracks * out->heads * out->sectrac;
368 * Print a textual translation of the drive (density) type described
369 * by `in' to stdout. The string uses the same form that is parseable
373 print_fmt(struct fd_type in)
377 secsize = 128 << in.secsize;
379 case FDC_250KBPS: speed = 250; break;
380 case FDC_300KBPS: speed = 300; break;
381 case FDC_500KBPS: speed = 500; break;
382 case FDC_1MBPS: speed = 1000; break;
383 default: speed = 1; break;
386 printf("%d,%d,%#x,%#x,%d,%d,%d,%#x,%d,%d",
387 in.sectrac, secsize, in.datalen, in.gap, in.tracks,
388 speed, in.heads, in.f_gap, in.f_inter, in.offset_side2);
389 if (in.flags & FL_MFM)
391 if (in.flags & FL_2STEP)
393 if (in.flags & FL_PERPND)
395 if (in.flags & FL_AUTO)
401 * Based on `size' (in kilobytes), walk through the table of known
402 * densities for drive type `type' and see if we can find one. If
403 * found, return it (as a pointer to static storage), otherwise return
407 get_fmt(int size, enum fd_drivetype type)
410 struct fd_type *fdtp;
417 fdtp = fd_types_360k;
418 n = sizeof fd_types_360k / sizeof(struct fd_type);
422 fdtp = fd_types_720k;
423 n = sizeof fd_types_720k / sizeof(struct fd_type);
428 n = sizeof fd_types_12m / sizeof(struct fd_type);
432 fdtp = fd_types_144m;
433 n = sizeof fd_types_144m / sizeof(struct fd_type);
437 fdtp = fd_types_288m;
438 n = sizeof fd_types_288m / sizeof(struct fd_type);
443 return fd_types_auto;
445 for (i = 0; i < n; i++, fdtp++) {
446 fdtp->size = fdtp->sectrac * fdtp->heads * fdtp->tracks;
447 if (((128 << fdtp->secsize) * fdtp->size / 1024) == size)
454 * Parse a number from `s'. If the string cannot be converted into a
455 * number completely, return -1, otherwise 0. The result is returned
459 getnum(const char *s, int *res)
464 ul = strtoul(s, &cp, 0);
473 * Return a short name and a verbose description for the drive
477 getname(enum fd_drivetype t, const char **name, const char **descr)
483 *descr = "unknown drive type";
488 *descr = "5.25\" double-density";
493 *descr = "5.25\" high-density";
498 *descr = "3.5\" double-density";
503 *descr = "3.5\" high-density";
508 *descr = "3.5\" extra-density";