1 /* 2 * Copyright (c) 1992 OMRON Corporation. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * OMRON Corporation. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)sd.c 8.1 (Berkeley) 06/10/93 12 */ 13 14 /* 15 * sd.c -- SCSI DISK device driver 16 * by A.Fujita, FEB-26-1992 17 */ 18 19 20 /* 21 * SCSI CCS (Command Command Set) disk driver. 22 */ 23 #define NSD 2 24 25 #include <sys/param.h> 26 #include <sys/disklabel.h> 27 #include <luna68k/dev/scsireg.h> 28 #include <luna68k/stand/saio.h> 29 #include <luna68k/stand/device.h> 30 31 32 int sdinit(), sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr(); 33 34 struct driver sddriver = { 35 sdinit, "sd", sdstart, sdgo, sdintr, 36 }; 37 38 struct disklabel sdlabel[NSD]; 39 40 struct sd_softc { 41 struct hp_device *sc_hd; 42 struct devqueue sc_dq; 43 int sc_format_pid; /* process using "format" mode */ 44 short sc_flags; 45 short sc_type; /* drive type */ 46 short sc_punit; /* physical unit (scsi lun) */ 47 u_short sc_bshift; /* convert device blocks to DEV_BSIZE blks */ 48 u_int sc_blks; /* number of blocks on device */ 49 int sc_blksize; /* device block size in bytes */ 50 u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */ 51 } sd_softc[NSD]; 52 53 /* sc_flags values */ 54 #define SDF_ALIVE 0x1 55 56 #define sdunit(x) ((minor(x) >> 3) & 0x7) 57 #define sdpart(x) (minor(x) & 0x7) 58 #define sdpunit(x) ((x) & 7) 59 60 static struct scsi_inquiry inqbuf; 61 static struct scsi_fmt_cdb inq = { 62 6, 63 CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 64 }; 65 66 static u_long capbuf[2]; 67 struct scsi_fmt_cdb cap = { 68 10, 69 CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 70 }; 71 72 int 73 sdident(sc, hd) 74 struct sd_softc *sc; 75 struct hp_device *hd; 76 { 77 char idstr[32]; 78 int unit; 79 register int ctlr, slave; 80 register int i; 81 register int tries = 10; 82 83 ctlr = hd->hp_ctlr; 84 slave = hd->hp_slave; 85 unit = sc->sc_punit; 86 87 /* 88 * See if unit exists and is a disk then read block size & nblocks. 89 */ 90 while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) { 91 if (i < 0 || --tries < 0) 92 return (-1); 93 if (i == STS_CHECKCOND) { 94 u_char sensebuf[8]; 95 struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 96 97 scsi_request_sense(ctlr, slave, unit, sensebuf, 8); 98 if (sp->class == 7 && sp->key == 6) 99 /* drive doing an RTZ -- give it a while */ 100 DELAY(1000000); 101 } 102 DELAY(1000); 103 } 104 if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf, 105 sizeof(inqbuf)) || 106 scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf, 107 sizeof(capbuf))) 108 /* doesn't exist or not a CCS device */ 109 return (-1); 110 111 switch (inqbuf.type) { 112 case 0: /* disk */ 113 case 4: /* WORM */ 114 case 5: /* CD-ROM */ 115 case 7: /* Magneto-optical */ 116 break; 117 default: /* not a disk */ 118 return (-1); 119 } 120 sc->sc_blks = capbuf[0]; 121 sc->sc_blksize = capbuf[1]; 122 123 bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 124 for (i = 27; i > 23; --i) 125 if (idstr[i] != ' ') 126 break; 127 idstr[i+1] = 0; 128 for (i = 23; i > 7; --i) 129 if (idstr[i] != ' ') 130 break; 131 idstr[i+1] = 0; 132 for (i = 7; i >= 0; --i) 133 if (idstr[i] != ' ') 134 break; 135 idstr[i+1] = 0; 136 printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8], 137 &idstr[24]); 138 139 printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 140 if (sc->sc_blksize != DEV_BSIZE) { 141 if (sc->sc_blksize < DEV_BSIZE) { 142 printf("sd%d: need %d byte blocks - drive ignored\n", 143 unit, DEV_BSIZE); 144 return (-1); 145 } 146 for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1) 147 ++sc->sc_bshift; 148 sc->sc_blks <<= sc->sc_bshift; 149 } 150 sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 151 return(inqbuf.type); 152 } 153 154 int 155 sdinit(hd) 156 register struct hp_device *hd; 157 { 158 register struct sd_softc *sc = &sd_softc[hd->hp_unit]; 159 register struct disklabel *lp; 160 char *msg, *readdisklabel(); 161 162 #ifdef DEBUG 163 printf("sdinit: hd->hp_unit = %d\n", hd->hp_unit); 164 printf("sdinit: hd->hp_ctlr = %d, hd->hp_slave = %d\n", 165 hd->hp_ctlr, hd->hp_slave); 166 #endif 167 sc->sc_hd = hd; 168 sc->sc_punit = sdpunit(hd->hp_flags); 169 sc->sc_type = sdident(sc, hd); 170 if (sc->sc_type < 0) 171 return(0); 172 173 /* 174 * Use the default sizes until we've read the label, 175 * or longer if there isn't one there. 176 */ 177 lp = &sdlabel[hd->hp_unit]; 178 179 if (lp->d_secpercyl == 0) { 180 lp->d_secsize = DEV_BSIZE; 181 lp->d_nsectors = 32; 182 lp->d_ntracks = 20; 183 lp->d_secpercyl = 32*20; 184 lp->d_npartitions = 1; 185 lp->d_partitions[0].p_offset = 0; 186 lp->d_partitions[0].p_size = LABELSECTOR + 1; 187 } 188 189 /* 190 * read disklabel 191 */ 192 if (msg = readdisklabel(hd->hp_slave, sdstrategy, lp)) { 193 if (msg != NULL) 194 printf("sd%d: %s\n", hd->hp_unit, msg); 195 } 196 197 sc->sc_flags = SDF_ALIVE; 198 return(1); 199 } 200 201 int 202 sdopen(io) 203 struct iob *io; 204 { 205 register int unit = io->i_unit; 206 register struct disklabel *lp; 207 208 if (unit < 0 || unit >= NSD) 209 return(-1); 210 211 lp = &sdlabel[unit]; 212 io->i_boff = lp->d_partitions[io->i_boff].p_offset; 213 } 214 215 static struct scsi_fmt_cdb cdb_read = { 216 10, 217 CMD_READ_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0 218 }; 219 220 static struct scsi_fmt_cdb cdb_write = { 221 6, 222 CMD_WRITE_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0 223 }; 224 225 int 226 sdstrategy(io, func) 227 register struct iob *io; 228 register int func; 229 { 230 int unit = io->i_unit; 231 struct sd_softc *sc = &sd_softc[unit]; 232 struct scsi_fmt_cdb *cdb; 233 daddr_t blk = io->i_bn >> sc->sc_bshift; 234 u_int nblk = io->i_cc >> sc->sc_bshift; 235 int stat, ctlr, slave, i; 236 237 if (unit < 0 || unit >= NSD) 238 return(-1); 239 240 ctlr = sc->sc_hd->hp_ctlr; 241 slave = sc->sc_hd->hp_slave; 242 243 if (func == READ) 244 cdb = &cdb_read; 245 else 246 cdb = &cdb_write; 247 248 cdb->cdb[2] = (blk & 0xff000000) >> 24; 249 cdb->cdb[3] = (blk & 0x00ff0000) >> 16; 250 cdb->cdb[4] = (blk & 0x0000ff00) >> 8; 251 cdb->cdb[5] = (blk & 0x000000ff); 252 253 cdb->cdb[7] = ((nblk >> DEV_BSHIFT) & 0xff00) >> 8; 254 cdb->cdb[8] = ((nblk >> DEV_BSHIFT) & 0x00ff); 255 256 #ifdef DEBUG 257 printf("sdstrategy: io->i_unit = %d\n", io->i_unit); 258 printf("sdstrategy: blk = %d (0x%x), nblk = %d (0x%x)\n", blk, blk, nblk, nblk); 259 for (i = 0; i < 10; i++) 260 printf("sdstrategy: cdb[%d] = 0x%x\n", i, cdb->cdb[i]); 261 printf("sdstrategy: ctlr = %d, slave = %d\n", ctlr, slave); 262 #endif 263 stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb, io->i_ma, io->i_cc); 264 265 return(io->i_cc); 266 } 267 268 int 269 sdustart() 270 { 271 } 272 273 int 274 sdstart() 275 { 276 } 277 278 int 279 sdgo() 280 { 281 } 282 283 int 284 sdintr() 285 { 286 } 287 288 int 289 sdread(dev, blk, nblk, buff, len) 290 dev_t dev; 291 u_int blk; 292 u_int nblk; 293 u_char *buff; 294 u_int len; 295 { 296 register int unit = sdunit(dev); 297 register int part = sdpart(dev); 298 struct sd_softc *sc = &sd_softc[unit]; 299 struct scsi_fmt_cdb *cdb; 300 int stat, ctlr, slave; 301 302 ctlr = sc->sc_hd->hp_ctlr; 303 slave = sc->sc_hd->hp_slave; 304 305 cdb = &cdb_read; 306 307 cdb->cdb[2] = (blk & 0xff000000) >> 24; 308 cdb->cdb[3] = (blk & 0x00ff0000) >> 16; 309 cdb->cdb[4] = (blk & 0x0000ff00) >> 8; 310 cdb->cdb[5] = (blk & 0x000000ff); 311 312 cdb->cdb[7] = (nblk & 0xff00) >> 8; 313 cdb->cdb[8] = (nblk & 0x00ff); 314 315 stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb, buff, len); 316 317 if (stat == 0) 318 return(1); 319 else 320 return(0); 321 } 322 323 int 324 sdioctl(dev, data) 325 dev_t dev; 326 u_long data[]; 327 { 328 register int unit = sdunit(dev); 329 register int part = sdpart(dev); 330 register struct disklabel *lp; 331 332 if (unit < 0 || unit >= NSD) 333 return(0); 334 335 if (part < 0 || part >= MAXPARTITIONS) 336 return(0); 337 338 lp = &sdlabel[unit]; 339 data[0] = lp->d_partitions[part].p_offset; 340 data[1] = lp->d_partitions[part].p_size; 341 342 return(1); 343 } 344