NetBSD/sys/arch/x68k/stand/libsa/fd.c
2001-10-15 16:13:39 +00:00

127 lines
3.4 KiB
C

/* $NetBSD: fd.c,v 1.2 2001/10/15 16:13:40 minoura Exp $ */
/*
* Copyright (c) 2001 MINOURA Makoto.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/disklabel.h>
#include <lib/libsa/stand.h>
#include "fdvar.h"
#include "iocs.h"
int fdopen(struct open_file *, int, int);
int fdclose(struct open_file*);
int fdstrategy(void *devdata, int rw, daddr_t blk, size_t, void*, size_t*);
int
fdopen (struct open_file *f, int id, int part)
{
int error;
struct fd_softc *sc;
struct fdfmt fdfmt;
if (id < 0 || id > 3)
return ENXIO;
sc = alloc(sizeof (struct fd_softc));
/* lock the medium */
error = IOCS_B_DRVCHK((0x90 + id) << 8, 2);
if ((error & 2) == 0)
return ENXIO;
/* detect the sector size */
error = IOCS_B_RECALI((0x90 + id) << 8);
error = fd_check_format (id, 0, &sc->fmt);
if (error < 0) {
IOCS_B_DRVCHK((0x90 + id) << 8, 3); /* unlock */
free(sc, sizeof (struct fd_softc));
return -error;
}
/* check the second side */
error = fd_check_format (id, 1, &fdfmt);
if (error == 0) /* valid second side; set the #heads */
sc->fmt.maxsec.H = fdfmt.maxsec.H;
sc->unit = id;
f->f_devdata = sc;
return 0;
}
int
fdclose (struct open_file *f)
{
struct fd_softc *sc = f->f_devdata;
IOCS_B_DRVCHK((0x90 + sc->unit) << 8, 3);
free (sc, sizeof (struct fd_softc));
return 0;
}
int
fdstrategy (void *arg, int rw, daddr_t dblk, size_t size,
void *buf, size_t *rsize)
{
struct fd_softc *sc = arg;
int cyl, head, sect;
int nhead, nsect;
int error, nbytes;
if (size == 0) {
if (rsize)
*rsize = 0;
return 0;
}
nbytes = howmany (size, 128 << sc->fmt.minsec.N)
* (128 << sc->fmt.minsec.N);
nhead = sc->fmt.maxsec.H - sc->fmt.minsec.H + 1;
nsect = sc->fmt.maxsec.R - sc->fmt.minsec.R + 1;
sect = dblk % nsect + sc->fmt.minsec.R;
head = (dblk / nsect) % nhead + sc->fmt.minsec.H;
cyl = (dblk / nsect) / nhead + sc->fmt.minsec.C;
error = IOCS_B_READ((sc->unit+0x90)*256 + 0x70,
((sc->fmt.minsec.N << 24) |
(cyl << 16) |
(head << 8) |
(sect)),
nbytes,
buf);
if (error & 0xf8ffff00) {
nbytes = 0;
error = EIO;
} else
error = 0;
if (rsize)
*rsize = nbytes;
return error;
}