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