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