sd.c revision 1.2 1 /* $NetBSD: sd.c,v 1.2 2013/01/13 04:39:28 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 %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
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_slave, sdstrategy, 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