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