Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/x68k/dev Add floppy format support. Mostly taken f...
details: https://anonhg.NetBSD.org/src/rev/e790c9d36233
branches: trunk
changeset: 782080:e790c9d36233
user: tsutsui <tsutsui%NetBSD.org@localhost>
date: Sun Oct 14 18:38:32 2012 +0000
description:
Add floppy format support. Mostly taken from sys/dev/isa/fd.c.
Tested both fdNa (1232KB, 1024bytes/sector, 8sectors/track) and
fdNc (1200KB, 512bytes/sector, 15sectors/track) format on X68030
using fdformat(1).
Finally we can prepare NetBSD/x68k install floppies without Human68k
(except actual initial bootstrap).
diffstat:
sys/arch/x68k/dev/fd.c | 283 +++++++++++++++++++++++++++++++++++++++++----
sys/arch/x68k/dev/fdreg.h | 51 ++++++++-
2 files changed, 303 insertions(+), 31 deletions(-)
diffs (truncated from 493 to 300 lines):
diff -r 43330750df32 -r e790c9d36233 sys/arch/x68k/dev/fd.c
--- a/sys/arch/x68k/dev/fd.c Sun Oct 14 18:37:55 2012 +0000
+++ b/sys/arch/x68k/dev/fd.c Sun Oct 14 18:38:32 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fd.c,v 1.103 2012/10/14 17:25:59 tsutsui Exp $ */
+/* $NetBSD: fd.c,v 1.104 2012/10/14 18:38:32 tsutsui Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.103 2012/10/14 17:25:59 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.104 2012/10/14 18:38:32 tsutsui Exp $");
#include "opt_ddb.h"
#include "opt_m68k_arch.h"
@@ -87,6 +87,7 @@
#include <sys/uio.h>
#include <sys/syslog.h>
#include <sys/queue.h>
+#include <sys/proc.h>
#include <sys/fdio.h>
#include <sys/rnd.h>
@@ -112,6 +113,9 @@
#define FDUNIT(dev) (minor(dev) / 8)
#define FDTYPE(dev) (minor(dev) % 8)
+/* (mis)use device use flag to identify format operation */
+#define B_FORMAT B_DEVPRIVATE
+
enum fdc_state {
DEVIDLE = 0,
MOTORWAIT,
@@ -184,19 +188,29 @@
int size; /* size of disk in sectors */
int step; /* steps per cylinder */
int rate; /* transfer speed code */
+ uint8_t fillbyte; /* format fill byte */
+ uint8_t interleave; /* interleave factor (formatting) */
const char *name;
};
/* The order of entries in the following table is important -- BEWARE! */
struct fd_type fd_types[] = {
- { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS, "1.2MB/[1024bytes/sector]" }, /* 1.2 MB japanese format */
- { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,"1.44MB" }, /* 1.44MB diskette */
- { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, "1.2MB" }, /* 1.2 MB AT-diskettes */
- { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, "360KB/AT" }, /* 360kB in 1.2MB drive */
- { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, "360KB/PC" }, /* 360kB PC diskettes */
- { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, "720KB" }, /* 3.5" 720kB diskette */
- { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, "720KB/x" }, /* 720kB in 1.2MB drive */
- { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS, "360KB/x" }, /* 360kB in 720kB drive */
+ { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS, 0xf6, 1,
+ "1.2MB/[1024bytes/sector]" }, /* 1.2 MB japanese format */
+ { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS, 0xf6, 1,
+ "1.44MB" }, /* 1.44MB diskette */
+ { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, 0xf6, 1,
+ "1.2MB" }, /* 1.2 MB AT-diskettes */
+ { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, 0xf6, 1,
+ "360KB/AT" }, /* 360kB in 1.2MB drive */
+ { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, 0xf6, 1,
+ "360KB/PC" }, /* 360kB PC diskettes */
+ { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, 0xf6, 1,
+ "720KB" }, /* 3.5" 720kB diskette */
+ { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, 0xf6, 1,
+ "720KB/x" }, /* 720kB in 1.2MB drive */
+ { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS, 0xf6, 1,
+ "360KB/x" }, /* 360kB in 720kB drive */
};
/* software state, per disk (with up to 4 disks per ctlr) */
@@ -283,6 +297,7 @@
void fdcretry(struct fdc_softc *);
void fdfinish(struct fd_softc *, struct buf *);
inline struct fd_type *fd_dev_to_type(struct fd_softc *, dev_t);
+int fdformat(dev_t, struct ne7_fd_formb *, struct lwp *);
static int fdcpoll(struct fdc_softc *);
static int fdgetdisklabel(struct fd_softc *, dev_t);
static void fd_do_eject(struct fdc_softc *, int);
@@ -659,7 +674,8 @@
}
if (bp->b_blkno < 0 ||
- (bp->b_bcount % FDC_BSIZE) != 0) {
+ ((bp->b_bcount % FDC_BSIZE) != 0 &&
+ (bp->b_flags & B_FORMAT) == 0)) {
DPRINTF(("fdstrategy: unit=%d, blkno=%" PRId64 ", "
"bcount=%d\n", unit,
bp->b_blkno, bp->b_bcount));
@@ -943,6 +959,9 @@
break;
}
+ /* clear flags */
+ fd->sc_opts &= ~(FDOPT_NORETRY | FDOPT_SILENT);
+
if ((fd->sc_flags & FD_OPEN) == 0) {
bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout,
(1 << unit));
@@ -1059,6 +1078,7 @@
int read, head, sec, pos, i, sectrac, nblks;
int tmp;
struct fd_type *type;
+ struct ne7_fd_formb *finfo = NULL;
loop:
fd = TAILQ_FIRST(&fdc->sc_drives);
@@ -1088,6 +1108,9 @@
goto loop;
}
+ if (bp->b_flags & B_FORMAT)
+ finfo = (struct ne7_fd_formb *)bp->b_data;
+
switch (fdc->sc_state) {
case DEVIDLE:
DPRINTF(("fdcintr: in DEVIDLE\n"));
@@ -1154,10 +1177,13 @@
doio:
DPRINTF(("fdcintr: DOIO: "));
type = fd->sc_type;
+ if (finfo != NULL)
+ fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) -
+ (char *)finfo;
sectrac = type->sectrac;
pos = fd->sc_blkno % (sectrac * (1 << (type->secsize - 2)));
sec = pos / (1 << (type->secsize - 2));
- if (type->secsize == 2) {
+ if (finfo != NULL || type->secsize == 2) {
fd->sc_part = SEC_P11;
nblks = (sectrac - sec) << (type->secsize - 2);
nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
@@ -1189,7 +1215,8 @@
nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE);
DPRINTF((" %d\n", nblks));
fd->sc_nblks = nblks;
- fd->sc_nbytes = nblks * FDC_BSIZE;
+ fd->sc_nbytes =
+ (finfo != NULL) ? bp->b_bcount : nblks * FDC_BSIZE;
head = (fd->sc_blkno
% (type->seccyl * (1 << (type->secsize - 2))))
/ (type->sectrac * (1 << (type->secsize - 2)));
@@ -1220,23 +1247,37 @@
DPRINTF(("C H R N: %d %d %d %d\n", fd->sc_cylin, head, sec,
type->secsize));
- if (fd->sc_part != SEC_P11)
+ if (finfo == NULL && fd->sc_part != SEC_P11)
goto docopy;
fdc_dmastart(fdc, read, (char *)bp->b_data + fd->sc_skip,
fd->sc_nbytes);
- if (read)
- out_fdc(iot, ioh, NE7CMD_READ); /* READ */
- else
- out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */
- out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
- out_fdc(iot, ioh, bp->b_cylinder); /* cylinder */
- out_fdc(iot, ioh, head);
- out_fdc(iot, ioh, sec + 1); /* sector +1 */
- out_fdc(iot, ioh, type->secsize); /* sector size */
- out_fdc(iot, ioh, type->sectrac); /* sectors/track */
- out_fdc(iot, ioh, type->gap1); /* gap1 size */
- out_fdc(iot, ioh, type->datalen); /* data length */
+ if (finfo != NULL) {
+ /* formatting */
+ if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) {
+ fdc->sc_errors = 4;
+ fdcretry(fdc);
+ goto loop;
+ }
+ out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
+ out_fdc(iot, ioh, finfo->fd_formb_secshift);
+ out_fdc(iot, ioh, finfo->fd_formb_nsecs);
+ out_fdc(iot, ioh, finfo->fd_formb_gaplen);
+ out_fdc(iot, ioh, finfo->fd_formb_fillbyte);
+ } else {
+ if (read)
+ out_fdc(iot, ioh, NE7CMD_READ); /* READ */
+ else
+ out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */
+ out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
+ out_fdc(iot, ioh, bp->b_cylinder); /* cylinder */
+ out_fdc(iot, ioh, head);
+ out_fdc(iot, ioh, sec + 1); /* sector +1 */
+ out_fdc(iot, ioh, type->secsize); /* sector size */
+ out_fdc(iot, ioh, type->sectrac); /* sectors/track */
+ out_fdc(iot, ioh, type->gap1); /* gap1 size */
+ out_fdc(iot, ioh, type->datalen); /* data length */
+ }
fdc->sc_state = IOCOMPLETE;
disk_busy(&fd->sc_dk);
@@ -1385,7 +1426,7 @@
fd->sc_skip += fd->sc_nbytes;
fd->sc_bcount -= fd->sc_nbytes;
DPRINTF(("fd->sc_bcount = %d\n", fd->sc_bcount));
- if (fd->sc_bcount > 0) {
+ if (finfo == NULL && fd->sc_bcount > 0) {
bp->b_cylinder = fd->sc_blkno
/ (fd->sc_type->seccyl
* (1 << (fd->sc_type->secsize - 2)));
@@ -1505,6 +1546,9 @@
fd = TAILQ_FIRST(&fdc->sc_drives);
bp = bufq_peek(fd->sc_q);
+ if (fd->sc_opts & FDOPT_NORETRY)
+ goto fail;
+
switch (fdc->sc_errors) {
case 0:
/* try again */
@@ -1524,9 +1568,12 @@
break;
default:
- diskerr(bp, "fd", "hard error", LOG_PRINTF,
- fd->sc_skip, (struct disklabel *)NULL);
- fdcpstatus(7, fdc);
+ fail:
+ if ((fd->sc_opts & FDOPT_SILENT) == 0) {
+ diskerr(bp, "fd", "hard error", LOG_PRINTF,
+ fd->sc_skip, (struct disklabel *)NULL);
+ fdcpstatus(7, fdc);
+ }
bp->b_error = EIO;
fdfinish(fd, bp);
@@ -1539,9 +1586,15 @@
{
struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev));
struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev));
+ struct fdformat_parms *form_parms;
+ struct fdformat_cmd *form_cmd;
+ struct ne7_fd_formb *fd_formb;
int part = DISKPART(dev);
struct disklabel buffer;
int error;
+ unsigned int scratch;
+ int il[FD_MAX_NSEC + 1];
+ int i, j;
DPRINTF(("fdioctl:"));
switch (cmd) {
@@ -1591,6 +1644,134 @@
error = writedisklabel(dev, fdstrategy, &buffer, NULL);
return error;
+ case FDIOCGETFORMAT:
+ DPRINTF(("FDIOCGETFORMAT\n"));
+ form_parms = (struct fdformat_parms *)addr;
+ form_parms->fdformat_version = FDFORMAT_VERSION;
+ form_parms->nbps = 128 * (1 << fd->sc_type->secsize);
+ form_parms->ncyl = fd->sc_type->cyls;
+ form_parms->nspt = fd->sc_type->sectrac;
+ form_parms->ntrk = fd->sc_type->heads;
+ form_parms->stepspercyl = fd->sc_type->step;
+ form_parms->gaplen = fd->sc_type->gap2;
+ form_parms->fillbyte = fd->sc_type->fillbyte;
+ form_parms->interleave = fd->sc_type->interleave;
+ switch (fd->sc_type->rate) {
+ case FDC_500KBPS:
+ form_parms->xfer_rate = 500 * 1024;
+ break;
+ case FDC_300KBPS:
+ form_parms->xfer_rate = 300 * 1024;
+ break;
+ case FDC_250KBPS:
+ form_parms->xfer_rate = 250 * 1024;
+ break;
+ default:
+ return EINVAL;
+ }
+ return 0;
+
+ case FDIOCSETFORMAT:
+ DPRINTF(("FDIOCSETFORMAT\n"));
+ if((flag & FWRITE) == 0)
+ return EBADF; /* must be opened for writing */
+ form_parms = (struct fdformat_parms *)addr;
+ if (form_parms->fdformat_version != FDFORMAT_VERSION)
+ return EINVAL; /* wrong version of formatting prog */
+
+ scratch = form_parms->nbps >> 7;
+ if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 ||
+ scratch & ~(1 << (ffs(scratch) - 1)))
+ /* not a power-of-two multiple of 128 */
+ return EINVAL;
+
+ switch (form_parms->xfer_rate) {
+ case 500 * 1024:
+ fd->sc_type->rate = FDC_500KBPS;
+ break;
+ case 300 * 1024:
+ fd->sc_type->rate = FDC_300KBPS;
+ break;
+ case 250 * 1024:
Home |
Main Index |
Thread Index |
Old Index