1 /* $NetBSD: fd.c,v 1.8 2014/03/08 03:20:24 isaki Exp $ */ 2 3 /* 4 * Copyright (c) 2001 MINOURA Makoto. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/disklabel.h> 30 #include <lib/libsa/stand.h> 31 32 #include "libx68k.h" 33 #include "fdvar.h" 34 #include "iocs.h" 35 36 /* fdopen(struct open_file *f, int id, int part) */ 37 int 38 fdopen(struct open_file *f, ...) 39 { 40 int error; 41 struct fd_softc *sc; 42 struct fdfmt fdfmt; 43 int id; 44 int part __unused; 45 va_list ap; 46 47 va_start(ap, f); 48 id = va_arg(ap, int); 49 part = va_arg(ap, int); 50 va_end(ap); 51 52 if (id < 0 || id > 3) 53 return ENXIO; 54 sc = alloc(sizeof (struct fd_softc)); 55 56 /* lock the medium */ 57 error = IOCS_B_DRVCHK((0x90 + id) << 8, 2); 58 if ((error & 2) == 0) 59 return ENXIO; 60 61 /* detect the sector size */ 62 error = IOCS_B_RECALI((0x90 + id) << 8); 63 error = fd_check_format(id, 0, &sc->fmt); 64 if (error < 0) { 65 IOCS_B_DRVCHK((0x90 + id) << 8, 3); /* unlock */ 66 dealloc(sc, sizeof(struct fd_softc)); 67 return -error; 68 } 69 70 /* check the second side */ 71 error = fd_check_format(id, 1, &fdfmt); 72 if (error == 0) /* valid second side; set the #heads */ 73 sc->fmt.maxsec.H = fdfmt.maxsec.H; 74 75 sc->unit = id; 76 f->f_devdata = sc; 77 78 return 0; 79 } 80 81 int 82 fdclose(struct open_file *f) 83 { 84 struct fd_softc *sc = f->f_devdata; 85 86 IOCS_B_DRVCHK((0x90 + sc->unit) << 8, 3); 87 dealloc(sc, sizeof(struct fd_softc)); 88 return 0; 89 } 90 91 int 92 fdstrategy(void *arg, int rw, daddr_t dblk, size_t size, 93 void *buf, size_t *rsize) 94 { 95 struct fd_softc *sc = arg; 96 int cyl, head, sect; 97 int nhead, nsect; 98 int error, nbytes; 99 100 if (size == 0) { 101 if (rsize) 102 *rsize = 0; 103 return 0; 104 } 105 nbytes = howmany(size, 128 << sc->fmt.minsec.N) 106 * (128 << sc->fmt.minsec.N); 107 108 nhead = sc->fmt.maxsec.H - sc->fmt.minsec.H + 1; 109 nsect = sc->fmt.maxsec.R - sc->fmt.minsec.R + 1; 110 111 sect = dblk % nsect + sc->fmt.minsec.R; 112 head = (dblk / nsect) % nhead + sc->fmt.minsec.H; 113 cyl = (dblk / nsect) / nhead + sc->fmt.minsec.C; 114 115 error = IOCS_B_READ((sc->unit + 0x90) * 256 + 0x70, 116 ((sc->fmt.minsec.N << 24) | 117 (cyl << 16) | 118 (head << 8) | 119 (sect)), 120 nbytes, 121 buf); 122 if (error & 0xf8ffff00) { 123 nbytes = 0; 124 error = EIO; 125 } else { 126 error = 0; 127 } 128 129 if (rsize) 130 *rsize = nbytes; 131 return error; 132 } 133