1 /* $NetBSD: sd.c,v 1.10 2011/02/08 20:20:14 rmind Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Van Jacobson of Lawrence Berkeley Laboratory and the Systems 10 * Programming Group of the University of Utah Computer Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah $Hdr: sd.c 1.9 92/12/21$ 37 * 38 * @(#)sd.c 8.1 (Berkeley) 6/10/93 39 */ 40 41 /* 42 * SCSI CCS disk driver 43 */ 44 45 #include <sys/param.h> 46 #include <sys/disklabel.h> 47 48 #include <machine/stdarg.h> 49 50 #include <lib/libsa/stand.h> 51 52 #include <hp300/stand/common/samachdep.h> 53 #include <hp300/stand/common/conf.h> 54 55 #define _IOCTL_ 56 #include <hp300/stand/common/scsireg.h> 57 #include <hp300/stand/common/scsivar.h> 58 59 struct sdminilabel { 60 u_short npart; 61 u_long offset[MAXPARTITIONS]; 62 }; 63 64 struct sd_softc { 65 int sc_ctlr; 66 int sc_unit; 67 int sc_part; 68 char sc_retry; 69 char sc_alive; 70 short sc_blkshift; 71 struct sdminilabel sc_pinfo; 72 }; 73 74 #define SDRETRY 2 75 76 static int sdinit(int ,int); 77 static int sdgetinfo(struct sd_softc *); 78 79 struct disklabel sdlabel; 80 struct sd_softc sd_softc[NSCSI][NSD]; 81 82 static int 83 sdinit(int ctlr, int unit) 84 { 85 struct sd_softc *ss = &sd_softc[ctlr][unit]; 86 u_char stat; 87 int capbuf[2]; 88 89 stat = scsi_test_unit_rdy(ctlr, unit); 90 if (stat) { 91 /* drive may be doing RTZ - wait a bit */ 92 if (stat == STS_CHECKCOND) { 93 DELAY(1000000); 94 stat = scsi_test_unit_rdy(ctlr, unit); 95 } 96 if (stat) { 97 printf("sd(%d,%d,0,0): init failed (stat=%x)\n", 98 ctlr, unit, stat); 99 return 0; 100 } 101 } 102 /* 103 * try to get the drive block size. 104 */ 105 capbuf[0] = 0; 106 capbuf[1] = 0; 107 stat = scsi_read_capacity(ctlr, unit, 108 (u_char *)capbuf, sizeof(capbuf)); 109 if (stat == 0) { 110 if (capbuf[1] > DEV_BSIZE) 111 for (; capbuf[1] > DEV_BSIZE; capbuf[1] >>= 1) 112 ++ss->sc_blkshift; 113 } 114 ss->sc_alive = 1; 115 return 1; 116 } 117 118 char io_buf[MAXBSIZE]; 119 120 static int 121 sdgetinfo(struct sd_softc *ss) 122 { 123 struct sdminilabel *pi = &ss->sc_pinfo; 124 struct disklabel *lp = &sdlabel; 125 char *msg; 126 int err, savepart; 127 size_t i; 128 129 memset((void *)lp, 0, sizeof *lp); 130 lp->d_secsize = (DEV_BSIZE << ss->sc_blkshift); 131 132 /* Disklabel is always from RAW_PART. */ 133 savepart = ss->sc_part; 134 ss->sc_part = RAW_PART; 135 err = sdstrategy(ss, F_READ, LABELSECTOR, 136 lp->d_secsize ? lp->d_secsize : DEV_BSIZE, io_buf, &i); 137 ss->sc_part = savepart; 138 139 if (err) { 140 printf("sdgetinfo: sdstrategy error %d\n", err); 141 return 0; 142 } 143 144 msg = getdisklabel(io_buf, lp); 145 if (msg) { 146 printf("sd(%d,%d,%d): WARNING: %s\n", 147 ss->sc_ctlr, ss->sc_unit, ss->sc_part, msg); 148 pi->npart = 3; 149 pi->offset[0] = pi->offset[1] = -1; 150 pi->offset[2] = 0; 151 } else { 152 pi->npart = lp->d_npartitions; 153 for (i = 0; i < pi->npart; i++) 154 pi->offset[i] = lp->d_partitions[i].p_size == 0 ? 155 -1 : lp->d_partitions[i].p_offset; 156 } 157 return 1; 158 } 159 160 int 161 sdopen(struct open_file *f, ...) 162 { 163 va_list ap; 164 int ctlr, unit, part; 165 struct sd_softc *ss; 166 167 va_start(ap, f); 168 ctlr = va_arg(ap, int); 169 unit = va_arg(ap, int); 170 part = va_arg(ap, int); 171 va_end(ap); 172 173 #ifdef SD_DEBUG 174 if (debug) 175 printf("sdopen: ctlr=%d unit=%d part=%d\n", 176 ctlr, unit, part); 177 #endif 178 179 if (ctlr >= NSCSI || scsialive(ctlr) == 0) 180 return EADAPT; 181 if (unit >= NSD) 182 return ECTLR; 183 ss = &sd_softc[ctlr][unit]; 184 ss->sc_part = part; 185 ss->sc_unit = unit; 186 ss->sc_ctlr = ctlr; 187 if (ss->sc_alive == 0) { 188 if (sdinit(ctlr, unit) == 0) 189 return ENXIO; 190 if (sdgetinfo(ss) == 0) 191 return ERDLAB; 192 } 193 if (part != RAW_PART && /* always allow RAW_PART to be opened */ 194 (part >= ss->sc_pinfo.npart || ss->sc_pinfo.offset[part] == -1)) 195 return EPART; 196 f->f_devdata = (void *)ss; 197 return 0; 198 } 199 200 int 201 sdclose(struct open_file *f) 202 { 203 struct sd_softc *ss = f->f_devdata; 204 205 /* 206 * Mark the disk `not alive' so that the disklabel 207 * will be re-loaded at next open. 208 */ 209 memset(ss, 0, sizeof(sd_softc)); 210 f->f_devdata = NULL; 211 212 return 0; 213 } 214 215 int 216 sdstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf, 217 size_t *rsize) 218 { 219 struct sd_softc *ss = devdata; 220 uint8_t *buf = v_buf; 221 int ctlr = ss->sc_ctlr; 222 int unit = ss->sc_unit; 223 u_int nblk = size >> ss->sc_blkshift; 224 daddr_t blk; 225 int stat; 226 227 if (size == 0) 228 return 0; 229 230 /* 231 * Don't do partition translation on the `raw partition'. 232 */ 233 blk = (dblk + ((ss->sc_part == RAW_PART) ? 0 : 234 ss->sc_pinfo.offset[ss->sc_part])) >> ss->sc_blkshift; 235 236 ss->sc_retry = 0; 237 238 #ifdef SD_DEBUG 239 if (debug) 240 printf("sdstrategy(%d,%d): size=%d blk=%d nblk=%d\n", 241 ctlr, unit, size, blk, nblk); 242 #endif 243 244 retry: 245 if (func == F_READ) 246 stat = scsi_tt_read(ctlr, unit, buf, size, blk, nblk); 247 else 248 stat = scsi_tt_write(ctlr, unit, buf, size, blk, nblk); 249 if (stat) { 250 printf("sd(%d,%d,%d): block=%x, error=0x%x\n", 251 ctlr, unit, ss->sc_part, blk, stat); 252 if (++ss->sc_retry > SDRETRY) 253 return EIO; 254 goto retry; 255 } 256 *rsize = size; 257 258 return 0; 259 } 260