1 /* $OpenBSD: sd.c,v 1.6 2020/12/09 18:10:19 krw Exp $ */ 2 /* $NetBSD: sd.c,v 1.5 2013/01/22 15:48:40 tsutsui Exp $ */ 3 4 /* 5 * Copyright (c) 1992 OMRON Corporation. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * OMRON Corporation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)sd.c 8.1 (Berkeley) 6/10/93 39 */ 40 /* 41 * Copyright (c) 1992, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * This code is derived from software contributed to Berkeley by 45 * OMRON Corporation. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. Neither the name of the University nor the names of its contributors 56 * may be used to endorse or promote products derived from this software 57 * without specific prior written permission. 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 * 71 * @(#)sd.c 8.1 (Berkeley) 6/10/93 72 */ 73 74 /* 75 * sd.c -- SCSI DISK device driver 76 * by A.Fujita, FEB-26-1992 77 */ 78 79 80 /* 81 * SCSI CCS (Command Command Set) disk driver. 82 */ 83 #include <sys/param.h> 84 #include <sys/disklabel.h> 85 #include <luna88k/stand/boot/samachdep.h> 86 #include <luna88k/stand/boot/scsireg.h> 87 #include <luna88k/stand/boot/scsivar.h> 88 89 struct sd_softc { 90 uint sc_ctlr; 91 uint sc_tgt; 92 uint sc_part; 93 94 short sc_type; /* drive type */ 95 short sc_punit; /* physical unit (scsi lun) */ 96 u_short sc_bshift; /* convert device blocks to DEV_BSIZE blks */ 97 daddr32_t sc_blks; /* number of blocks on device */ 98 int sc_blksize; /* device block size in bytes */ 99 100 struct disklabel sc_label; 101 struct scsi_softc sc_sc; 102 }; 103 104 struct sd_softc *sdinit(uint, uint); 105 static int sdident(struct sd_softc *); 106 107 static struct scsi_inquiry inqbuf; 108 static struct scsi_generic_cdb inq = { 109 6, 110 { CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 } 111 }; 112 113 static u_long capbuf[2]; 114 struct scsi_generic_cdb cap = { 115 10, 116 { CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 117 }; 118 119 int 120 sdident(struct sd_softc *sc) 121 { 122 #ifdef DEBUG 123 char idstr[32]; 124 #endif 125 uint ctlr, target, unit; 126 int i; 127 int tries = 10; 128 129 ctlr = sc->sc_ctlr; 130 target = sc->sc_tgt; 131 unit = sc->sc_punit; 132 133 if (scinit(&sc->sc_sc, ctlr) == 0) 134 return -1; 135 136 /* 137 * See if unit exists and is a disk then read block size & nblocks. 138 */ 139 while ((i = scsi_test_unit_rdy(&sc->sc_sc, target, unit)) != 0) { 140 if (i < 0 || --tries < 0) 141 return (-1); 142 if (i == STS_CHECKCOND) { 143 u_char sensebuf[8]; 144 struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 145 146 scsi_request_sense(&sc->sc_sc, target, unit, sensebuf, 147 sizeof sensebuf); 148 if (sp->class == 7 && sp->key == 6) 149 /* drive doing an RTZ -- give it a while */ 150 DELAY(1000000); 151 } 152 DELAY(1000); 153 } 154 if (scsi_immed_command(&sc->sc_sc, target, unit, &inq, 155 (u_char *)&inqbuf, sizeof(inqbuf)) || 156 scsi_immed_command(&sc->sc_sc, target, unit, &cap, 157 (u_char *)&capbuf, sizeof(capbuf))) 158 /* doesn't exist or not a CCS device */ 159 return (-1); 160 161 switch (inqbuf.type) { 162 case 0: /* disk */ 163 case 4: /* WORM */ 164 case 5: /* CD-ROM */ 165 case 7: /* Magneto-optical */ 166 break; 167 default: /* not a disk */ 168 return (-1); 169 } 170 sc->sc_blks = capbuf[0]; 171 sc->sc_blksize = capbuf[1]; 172 173 #ifdef DEBUG 174 memcpy(idstr, &inqbuf.vendor_id, 28); 175 for (i = 27; i > 23; --i) 176 if (idstr[i] != ' ') 177 break; 178 idstr[i+1] = 0; 179 for (i = 23; i > 7; --i) 180 if (idstr[i] != ' ') 181 break; 182 idstr[i+1] = 0; 183 for (i = 7; i >= 0; --i) 184 if (idstr[i] != ' ') 185 break; 186 idstr[i+1] = 0; 187 printf("sd(%d,%d): %s %s rev %s", ctlr, target, idstr, &idstr[8], 188 &idstr[24]); 189 190 printf(", %d bytes/sect x %d sectors\n", sc->sc_blksize, sc->sc_blks); 191 #endif 192 if (sc->sc_blksize != DEV_BSIZE) { 193 if (sc->sc_blksize < DEV_BSIZE) { 194 printf("sd(%d,%d): need %d byte blocks - drive ignored\n", 195 ctlr, target, DEV_BSIZE); 196 return (-1); 197 } 198 for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1) 199 ++sc->sc_bshift; 200 sc->sc_blks <<= sc->sc_bshift; 201 } 202 return(inqbuf.type); 203 } 204 205 struct sd_softc * 206 sdinit(uint unit, uint part) 207 { 208 struct sd_softc *sc; 209 struct disklabel *lp; 210 char *msg; 211 212 sc = alloc(sizeof *sc); 213 if (sc == NULL) 214 return NULL; 215 216 memset(sc, 0, sizeof *sc); 217 218 sc->sc_ctlr = unit / 10; 219 sc->sc_tgt = unit % 10; 220 sc->sc_part = part; 221 #ifdef DEBUG 222 printf("sdinit: ctlr = %d tgt = %d part = %d\n", 223 sc->sc_ctlr, sc->sc_tgt, sc->sc_part); 224 #endif 225 sc->sc_punit = 0; /* XXX no LUN support yet */ 226 sc->sc_type = sdident(sc); 227 if (sc->sc_type < 0) 228 return(NULL); 229 230 /* 231 * Use the default sizes until we've read the label, 232 * or longer if there isn't one there. 233 */ 234 lp = &sc->sc_label; 235 236 if (lp->d_secpercyl == 0) { 237 lp->d_secsize = DEV_BSIZE; 238 lp->d_nsectors = 32; 239 lp->d_ntracks = 20; 240 lp->d_secpercyl = 32*20; 241 lp->d_npartitions = 1; 242 lp->d_partitions[0].p_offset = 0; 243 lp->d_partitions[0].p_size = LABELSECTOR + 1; 244 } 245 246 /* 247 * read disklabel 248 */ 249 msg = readdisklabel(&sc->sc_sc, sc->sc_tgt, lp); 250 if (msg != NULL) 251 printf("sd(%d,%d): %s\n", sc->sc_ctlr, sc->sc_tgt, msg); 252 253 return sc; 254 } 255 256 int 257 sdopen(struct open_file *f, ...) 258 { 259 va_list ap; 260 struct sd_softc *sc; 261 int unit, part; 262 263 va_start(ap, f); 264 unit = va_arg(ap, int); 265 part = va_arg(ap, int); 266 va_end(ap); 267 268 if (part < 0 || part >= MAXPARTITIONS) 269 return(-1); 270 271 sc = sdinit(unit, part); 272 if (sc == NULL) 273 return -1; 274 275 f->f_devdata = (void *)sc; 276 return 0; 277 } 278 279 int 280 sdclose(struct open_file *f) 281 { 282 struct sd_softc *sc = f->f_devdata; 283 284 free(sc, sizeof *sc); 285 f->f_devdata = NULL; 286 287 return 0; 288 } 289 290 static struct scsi_generic_cdb cdb_read = { 291 10, 292 { CMD_READ_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 293 }; 294 295 static struct scsi_generic_cdb cdb_write = { 296 6, 297 { CMD_WRITE_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 298 }; 299 300 int 301 sdstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf, 302 size_t *rsize) 303 { 304 struct sd_softc *sc = devdata; 305 struct disklabel *lp; 306 uint8_t *buf = v_buf; 307 int target = sc->sc_tgt; 308 struct scsi_generic_cdb *cdb; 309 daddr32_t blk; 310 u_int nblk = size >> sc->sc_bshift; 311 int stat; 312 #ifdef DEBUG 313 int i; 314 #endif 315 316 lp = &sc->sc_label; 317 blk = dblk + (lp->d_partitions[sc->sc_part].p_offset >> sc->sc_bshift); 318 319 if (func == F_READ) 320 cdb = &cdb_read; 321 else 322 cdb = &cdb_write; 323 324 cdb->cdb[2] = (blk & 0xff000000) >> 24; 325 cdb->cdb[3] = (blk & 0x00ff0000) >> 16; 326 cdb->cdb[4] = (blk & 0x0000ff00) >> 8; 327 cdb->cdb[5] = (blk & 0x000000ff); 328 329 cdb->cdb[7] = ((nblk >> _DEV_BSHIFT) & 0xff00) >> 8; 330 cdb->cdb[8] = ((nblk >> _DEV_BSHIFT) & 0x00ff); 331 332 #ifdef DEBUG 333 printf("sdstrategy(%d,%d): blk = %lu (0x%lx), nblk = %u (0x%x)\n", 334 sc->sc_ctlr, sc->sc_tgt, (u_long)blk, (long)blk, nblk, nblk); 335 for (i = 0; i < 10; i++) 336 printf("cdb[%d] = 0x%x\n", i, cdb->cdb[i]); 337 #endif 338 stat = scsi_immed_command(&sc->sc_sc, target, sc->sc_punit, cdb, buf, 339 size); 340 if (rsize) 341 *rsize = size; 342 343 return 0; 344 } 345