1 /* $NetBSD: sd.c,v 1.11 2011/07/17 20:54:40 joerg 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 <lib/libsa/stand.h> 49 50 #include <hp300/stand/common/samachdep.h> 51 #include <hp300/stand/common/conf.h> 52 53 #define _IOCTL_ 54 #include <hp300/stand/common/scsireg.h> 55 #include <hp300/stand/common/scsivar.h> 56 57 struct sdminilabel { 58 u_short npart; 59 u_long offset[MAXPARTITIONS]; 60 }; 61 62 struct sd_softc { 63 int sc_ctlr; 64 int sc_unit; 65 int sc_part; 66 char sc_retry; 67 char sc_alive; 68 short sc_blkshift; 69 struct sdminilabel sc_pinfo; 70 }; 71 72 #define SDRETRY 2 73 74 static int sdinit(int ,int); 75 static int sdgetinfo(struct sd_softc *); 76 77 struct disklabel sdlabel; 78 struct sd_softc sd_softc[NSCSI][NSD]; 79 80 static int 81 sdinit(int ctlr, int unit) 82 { 83 struct sd_softc *ss = &sd_softc[ctlr][unit]; 84 u_char stat; 85 int capbuf[2]; 86 87 stat = scsi_test_unit_rdy(ctlr, unit); 88 if (stat) { 89 /* drive may be doing RTZ - wait a bit */ 90 if (stat == STS_CHECKCOND) { 91 DELAY(1000000); 92 stat = scsi_test_unit_rdy(ctlr, unit); 93 } 94 if (stat) { 95 printf("sd(%d,%d,0,0): init failed (stat=%x)\n", 96 ctlr, unit, stat); 97 return 0; 98 } 99 } 100 /* 101 * try to get the drive block size. 102 */ 103 capbuf[0] = 0; 104 capbuf[1] = 0; 105 stat = scsi_read_capacity(ctlr, unit, 106 (u_char *)capbuf, sizeof(capbuf)); 107 if (stat == 0) { 108 if (capbuf[1] > DEV_BSIZE) 109 for (; capbuf[1] > DEV_BSIZE; capbuf[1] >>= 1) 110 ++ss->sc_blkshift; 111 } 112 ss->sc_alive = 1; 113 return 1; 114 } 115 116 char io_buf[MAXBSIZE]; 117 118 static int 119 sdgetinfo(struct sd_softc *ss) 120 { 121 struct sdminilabel *pi = &ss->sc_pinfo; 122 struct disklabel *lp = &sdlabel; 123 char *msg; 124 int err, savepart; 125 size_t i; 126 127 memset((void *)lp, 0, sizeof *lp); 128 lp->d_secsize = (DEV_BSIZE << ss->sc_blkshift); 129 130 /* Disklabel is always from RAW_PART. */ 131 savepart = ss->sc_part; 132 ss->sc_part = RAW_PART; 133 err = sdstrategy(ss, F_READ, LABELSECTOR, 134 lp->d_secsize ? lp->d_secsize : DEV_BSIZE, io_buf, &i); 135 ss->sc_part = savepart; 136 137 if (err) { 138 printf("sdgetinfo: sdstrategy error %d\n", err); 139 return 0; 140 } 141 142 msg = getdisklabel(io_buf, lp); 143 if (msg) { 144 printf("sd(%d,%d,%d): WARNING: %s\n", 145 ss->sc_ctlr, ss->sc_unit, ss->sc_part, msg); 146 pi->npart = 3; 147 pi->offset[0] = pi->offset[1] = -1; 148 pi->offset[2] = 0; 149 } else { 150 pi->npart = lp->d_npartitions; 151 for (i = 0; i < pi->npart; i++) 152 pi->offset[i] = lp->d_partitions[i].p_size == 0 ? 153 -1 : lp->d_partitions[i].p_offset; 154 } 155 return 1; 156 } 157 158 int 159 sdopen(struct open_file *f, ...) 160 { 161 va_list ap; 162 int ctlr, unit, part; 163 struct sd_softc *ss; 164 165 va_start(ap, f); 166 ctlr = va_arg(ap, int); 167 unit = va_arg(ap, int); 168 part = va_arg(ap, int); 169 va_end(ap); 170 171 #ifdef SD_DEBUG 172 if (debug) 173 printf("sdopen: ctlr=%d unit=%d part=%d\n", 174 ctlr, unit, part); 175 #endif 176 177 if (ctlr >= NSCSI || scsialive(ctlr) == 0) 178 return EADAPT; 179 if (unit >= NSD) 180 return ECTLR; 181 ss = &sd_softc[ctlr][unit]; 182 ss->sc_part = part; 183 ss->sc_unit = unit; 184 ss->sc_ctlr = ctlr; 185 if (ss->sc_alive == 0) { 186 if (sdinit(ctlr, unit) == 0) 187 return ENXIO; 188 if (sdgetinfo(ss) == 0) 189 return ERDLAB; 190 } 191 if (part != RAW_PART && /* always allow RAW_PART to be opened */ 192 (part >= ss->sc_pinfo.npart || ss->sc_pinfo.offset[part] == -1)) 193 return EPART; 194 f->f_devdata = (void *)ss; 195 return 0; 196 } 197 198 int 199 sdclose(struct open_file *f) 200 { 201 struct sd_softc *ss = f->f_devdata; 202 203 /* 204 * Mark the disk `not alive' so that the disklabel 205 * will be re-loaded at next open. 206 */ 207 memset(ss, 0, sizeof(sd_softc)); 208 f->f_devdata = NULL; 209 210 return 0; 211 } 212 213 int 214 sdstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf, 215 size_t *rsize) 216 { 217 struct sd_softc *ss = devdata; 218 uint8_t *buf = v_buf; 219 int ctlr = ss->sc_ctlr; 220 int unit = ss->sc_unit; 221 u_int nblk = size >> ss->sc_blkshift; 222 daddr_t blk; 223 int stat; 224 225 if (size == 0) 226 return 0; 227 228 /* 229 * Don't do partition translation on the `raw partition'. 230 */ 231 blk = (dblk + ((ss->sc_part == RAW_PART) ? 0 : 232 ss->sc_pinfo.offset[ss->sc_part])) >> ss->sc_blkshift; 233 234 ss->sc_retry = 0; 235 236 #ifdef SD_DEBUG 237 if (debug) 238 printf("sdstrategy(%d,%d): size=%d blk=%d nblk=%d\n", 239 ctlr, unit, size, blk, nblk); 240 #endif 241 242 retry: 243 if (func == F_READ) 244 stat = scsi_tt_read(ctlr, unit, buf, size, blk, nblk); 245 else 246 stat = scsi_tt_write(ctlr, unit, buf, size, blk, nblk); 247 if (stat) { 248 printf("sd(%d,%d,%d): block=%x, error=0x%x\n", 249 ctlr, unit, ss->sc_part, blk, stat); 250 if (++ss->sc_retry > SDRETRY) 251 return EIO; 252 goto retry; 253 } 254 *rsize = size; 255 256 return 0; 257 } 258