1 /* $NetBSD: fd.c,v 1.7 2011/07/17 20:54:49 joerg 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, part; 44 va_list ap; 45 46 va_start(ap, f); 47 id = va_arg(ap, int); 48 part = va_arg(ap, int); 49 va_end(ap); 50 51 if (id < 0 || id > 3) 52 return ENXIO; 53 sc = alloc(sizeof (struct fd_softc)); 54 55 /* lock the medium */ 56 error = IOCS_B_DRVCHK((0x90 + id) << 8, 2); 57 if ((error & 2) == 0) 58 return ENXIO; 59 60 /* detect the sector size */ 61 error = IOCS_B_RECALI((0x90 + id) << 8); 62 error = fd_check_format(id, 0, &sc->fmt); 63 if (error < 0) { 64 IOCS_B_DRVCHK((0x90 + id) << 8, 3); /* unlock */ 65 dealloc(sc, sizeof(struct fd_softc)); 66 return -error; 67 } 68 69 /* check the second side */ 70 error = fd_check_format(id, 1, &fdfmt); 71 if (error == 0) /* valid second side; set the #heads */ 72 sc->fmt.maxsec.H = fdfmt.maxsec.H; 73 74 sc->unit = id; 75 f->f_devdata = sc; 76 77 return 0; 78 } 79 80 int 81 fdclose(struct open_file *f) 82 { 83 struct fd_softc *sc = f->f_devdata; 84 85 IOCS_B_DRVCHK((0x90 + sc->unit) << 8, 3); 86 dealloc(sc, sizeof(struct fd_softc)); 87 return 0; 88 } 89 90 int 91 fdstrategy(void *arg, int rw, daddr_t dblk, size_t size, 92 void *buf, size_t *rsize) 93 { 94 struct fd_softc *sc = arg; 95 int cyl, head, sect; 96 int nhead, nsect; 97 int error, nbytes; 98 99 if (size == 0) { 100 if (rsize) 101 *rsize = 0; 102 return 0; 103 } 104 nbytes = howmany(size, 128 << sc->fmt.minsec.N) 105 * (128 << sc->fmt.minsec.N); 106 107 nhead = sc->fmt.maxsec.H - sc->fmt.minsec.H + 1; 108 nsect = sc->fmt.maxsec.R - sc->fmt.minsec.R + 1; 109 110 sect = dblk % nsect + sc->fmt.minsec.R; 111 head = (dblk / nsect) % nhead + sc->fmt.minsec.H; 112 cyl = (dblk / nsect) / nhead + sc->fmt.minsec.C; 113 114 error = IOCS_B_READ((sc->unit + 0x90) * 256 + 0x70, 115 ((sc->fmt.minsec.N << 24) | 116 (cyl << 16) | 117 (head << 8) | 118 (sect)), 119 nbytes, 120 buf); 121 if (error & 0xf8ffff00) { 122 nbytes = 0; 123 error = EIO; 124 } else { 125 error = 0; 126 } 127 128 if (rsize) 129 *rsize = nbytes; 130 return error; 131 } 132